Android设计模式-观察者模式
原文地址 http://blog.csdn.net/qq_25806863/article/details/69218968
观察者模式是一种使用频率非常高的设计模式,最常用的地方就是订阅-发布系统。
这个模式的重要作用就是将观察者和被观察者解耦,使他们之间的依赖更小甚至没有。
定义
定义对象一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于他的对象都会得到通知并被自动更新。
使用场景
关联行为场景,这个关联是可拆分的。将观察者和被观察者封装在不同的对象中,可以各自独立的变化。
当一个对象改变时,有其他对象要进行相应的变化,但是他并不知道有多少个对象需要变化。
跨系统的消息交换长江,如消息队列,时事件总线等
UML
Subject : 抽象被观察者(Observeable),吧所有观察者对象的医用保存在一个集合里,每个主题都可以有任意数量的观察者,抽象被观察者提供一个接口,可以增加和删除观察者对象。
ConcreteSubject: 具体的被观察者,将有关状态存入具体的观察者对象,在具体的被观察者内部状态发生变化时,给所有注册的观察者发送通知。
Observer : 抽象观察者,定义了一个更新接口,使得在得到被观察者的通知时更新自己。
ConcreteObserver : 具体的观察者,实现了抽象观察者锁定义的接口,用来在收到通知时更新自己。
简单实现
订阅模式就是个观察者模式,订阅后,被订阅的有更新就会提示你。
拿微信公众号举个例子吧.Java提供的有Observer和Observable类,可以很方便的实现观察者模式。
先定义一个订阅者,实现更新方法。
---------------------
作者:喵了个呜s
来源:CSDN
原文:https://blog.csdn.net/qq_25806863/article/details/69218968
版权声明:本文为博主原创文章,转载请附上博文链接!
public class User implements Observer {
public String name; public User(String name) {
this.name = name;
} @Override
public void update(Observable o, Object arg) {
System.out.println("Hi "+name +",公众号更新了内容:"+arg);
}
}
定义一个可观察者,有变化时发布更新通知。
public class Gamedaily extends Observable {
public void postNewArticle(String content){
//内容发生改变
setChanged();
//通知所有订阅者改变的内容
notifyObservers(content);
}
}
使用
public class Client {
public static void main(String[] args) {
Gamedaily gamedaily = new Gamedaily();
User user1 = new User("user1");
User user2 = new User("user2");
User user3 = new User("user3");
//将观察者注册到可观察者的通知列表中。
gamedaily.addObserver(user1);
gamedaily.addObserver(user2);
gamedaily.addObserver(user3); gamedaily.postNewArticle("新文章来了");
}
}
输出
当公众号发布新文章的时候,所有订阅者都收到的通知,并作出相应的改变。一个公众号对应多个订阅者,并且完全没有耦合。
Android源码中的观察者模式
通常在ListView的内容变化时,我们会调用notifyDataSetChanged()这个方法,然后ListView里面的数据就会进行更新。这个感觉就像是观察者模式。ListView在观察者内容,内容变化发布通知之后ListView就会更新数据。
看一下这个方法。
package android.widget;
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
} public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
......
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
......
}
这段代码可以看到这应该是一个观察者模式,而且这个一个被观察者,里面提供了注册和注销观察者以及通知观察者的方法。
这些方法是通过DataSetObservable这个类调用的:
package android.database;
public class DataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
for (int i = mObservers.size() - ; i >= ; i--) {
mObservers.get(i).onChanged();
}
}
}
......
}
这个类继承自Observable,Observable中有一个protected final ArrayList<T> mObservers = new ArrayList<T>();,
用来保存注册的观察者。mDataSetObservable.registerObserver(observer)和mDataSetObservable.unregisterObserver(observer)分别就是增加和删除。 在notifyChanged方法中,循环这个集合,调用每一个观察者的onChanged()方法。 那么这些观察者是什么时候注册的呢?也就是ListView和Adapter什么时候成了订阅关系。在ListView的setAdapter()中
public class ListView extends AbsListView {
public void setAdapter(ListAdapter adapter) {
//如果已经有了一个adapter,注销这个adapter之前的观察者,
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
} ......
if (mHeaderViewInfos.size() > || mFooterViewInfos.size() > ) {
mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
//将新的adapter赋给mAdapter
mAdapter = adapter;
}
......
super.setAdapter(adapter); if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
//保存之前的数据个数
mOldItemCount = mItemCount;
//获取新的个数
mItemCount = mAdapter.getCount();
checkFocus();
//创建数据集观察者
mDataSetObserver = new AdapterDataSetObserver();
//注册观察者
mAdapter.registerDataSetObserver(mDataSetObserver);
...
}
} else {
...
} requestLayout();
}
}
AdapterDataSetObserver是ListView的父类AbsListView的内部类
package android.widget;
public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
ViewTreeObserver.OnTouchModeChangeListener,
RemoteViewsAdapter.RemoteAdapterConnectionCallback {
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
······
}
}
AdapterDataSetObserver是AdapterView.AdapterDataSetObserver的子类,所以要看super.onChanged()
package android.widget;
public abstract class AdapterView<T extends Adapter> extends ViewGroup {
class AdapterDataSetObserver extends DataSetObserver { private Parcelable mInstanceState = null; @Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount(); // Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == && mItemCount > ) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
//重新布局
requestLayout();
}
......
}
}
整理一下:当ListView数据变化时,调用Adapter的notifyDataSetChange方法,这个方法调用DataSetObservable的notifyChanged方法,这个方法又会调用所有观察者的onChanged方法,onChanged再调用重新布局View的方法,完成刷新数据的功能。
总结
优点
解除了观察者和被观察者的耦合,而且依赖的都是抽象,容易应对业务变化,各自的变化都不会影响另一个。
增强系统灵活性、可拓展性。
缺点
Java中的消息默认是顺序执行,如果一个观察者卡顿,会造成整个系统效率变低,可以考虑异步。
可能会引起无用的操作甚至错误的操作。
Android设计模式-观察者模式的更多相关文章
- Android设计模式---观察者模式小demo(一)
1,今天刚好看到了设计模式这一块来,而观察者模式是我一直想总结的,先来看看观察者模式的简单的定义吧 "当一个对象改变时,他的所有依赖者都会受到通知,并自动更新." 一般我们项目中就 ...
- Android设计模式—观察者模式
装载请标明出处:https://www.cnblogs.com/tangZH/p/11175120.html 观察者模式 说白了,就是一个对发生改变,所有依赖于它的对象也发生改变,这是一对多的关系. ...
- Android设计模式—— 观察者模式(以及EventBus的简单使用)
1.概述 观察者模式最常用的地方是GUI系统.订阅-发布系统.观察者模式的一个重要作用就是解耦,将观察者和被观察者解耦,使得他们之间的依赖性更小. 2.定义 定义对象间的一种一对多依赖关系,使得每当一 ...
- Android设计模式系列
http://www.cnblogs.com/qianxudetianxia/category/312863.html Android设计模式系列(12)--SDK源码之生成器模式(建造者模式) 摘要 ...
- 经常使用的android设计模式
一般来说,经常使用的android设计模式有下面8种:单例.工厂.观察者.代理.命令.适配器.合成.訪问者. 单例模式:目的是为了让系统中仅仅有一个调用对象,缺点是单例使其它程序过分依赖它,并且不 ...
- 18. 星际争霸之php设计模式--观察者模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- Android中观察者模式的升入理解
以前对Java中的观察者模式只知道一点皮毛,在接触Android的过程中,逐渐认识到观察者模式是如此的重要,android中许多地方都用到了观察者模式例如ContentResolver操作,来总结一下 ...
- Android设计模式(五岁以下儿童)--简单工厂模式
1.面试的时候问这个问题: 在ListView 的item小程序.很多不同的显示风格.或者是,为了更好地维护,不同的样式,应该怎么做? 我一下就想到的是工厂的模式,利用project,编写ViewFa ...
- linkin大话设计模式--观察者模式
linkin大话设计模式--观察者模式 观察者模式定义了对象间的一对多依赖关系,让一个或者多个观察者观察一个对象主题.当主题对象的状态发生改变的时候,系统能通知所有的依赖于此对象的观察者对象,从而能自 ...
随机推荐
- 上下文管理协议with_open,__enter__和__exit__(三十八)
在操作文件对象的时候可以这么写 with open('a.txt') as f: '代码块' 上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__ent ...
- Maven的配置以及Eclipse的设置
配置maven仓库 先找到我们解压的maven的conf目录里面的setting.xml 然后加入我们本地仓库的位置(这里仓库所在文件夹是自定义的,比如:我把它放在了D盘根目录的一个文件夹) ecli ...
- JS模板引擎handlebars.js的简单使用
handlebars.js的使用 首先我们要明白handlebars.js是干什么用的,我们知道使用jsp很麻烦, 于是我们开始使用freemarker等模板引擎,但这个只是针对服务器端来解 析的,那 ...
- Prometheus+grafana搭建
一.简介 1.1 Prometheus Prometheus是一套开源的监控系统,它将所有信息都存储为时间序列数据:因此实现一种Profiling监控方式,实时分析系统运行的状态.执行时间.调用次数等 ...
- 【已解决】ERR_BLOCKED_BY_XSS_AUDITOR:Chrome 在此网页上检测到了异常代码:解决办法
工作中,用Selenium自动化填表并获取结果时,程序一直安静的读取数据库,网页填表,获取结果,存库,但跑着跑着突然报错了. 排查后,原来不是Selenium的问题,是数据比较特殊,带了个双引号,如下 ...
- Swagger介绍-一套流行的API框架
简介 号称:世界最流行的API框架 官网:http://swagger.io/ 解决什么问题:在前后台分离的开发模式中,减小接口定义沟通成本,方便开发过程中测试,自动生成接口文档. 实例代码位置:ht ...
- memcache、redis原理对比
一.问题: 数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求. 二.解决方案: 1.通过高速服务器Cache缓存数据库数据 2.内存数据库 ( ...
- 学习windows编程 day6 之模拟记事本
//短的函数最好定义为宏 #define BUFFER(x,y) *(y*cxBuffer+x+pBuffer)//取出一个字符 //字符消息 //WM_CHAR,WM_DEADCHAR,WM_SYS ...
- ubuntu 18.04下character_set_server设置为utf8
打开/etc/mysql/mysql.conf.d/mysql.cnf添加以下代码: character-set-server = utf8 然后重启mysql即可
- luogu P1053 篝火晚会
传送门 首先如果题目的目标状态不是一个环就不合法 然后先把这个环搞出来,然后每个位置上的数对这个数对应的位置连边,可以发现有若干个环,而只要对这些环执行操作就好了,答案上界显然是\(n\).然后,如果 ...