推荐资源站:https://zhimalier.com/
今天接着昨天的内容聊,主要有观察者模式、代理模式、命令模式。--文章整理自博客园
观察者模式,是一种非常常见的设计模式,在很多系统中随处可见,尤其是涉及到数据状态发生变化需要通知的情况下。
本文以AbstractCursor为例子,展开分析。
观察者模式,Observer Pattern,是一个很实用的模式,本人曾经接触到的各种平台以及曾经参与项目中打印模板解释器中都用到了此模式。
1.意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
热门词汇:依赖 发布-订阅 事件 通知 更新 监听
2.结构
这是一个最简单的观察者模式,目标对象能够添加和删除观察者,当自己某种状态或者行为发生改变时,可通过notify通知注册的观察者进行更新操作。
分析AbstractCursor的具体情况,我们发现实际工作有时需要对观察者进行统一管理,甚至观察者类型有很多种而又可以分成几个系列,这个时候是要复杂的多,通过合理的分层这个问题很好解决。下面根据具体情况,我们画出android中abstractCurosr中用到的观察者模式结构图:
观察者分成了两个系列。
3.代码 列举其中相关核心代码如下:
public abstract class AbstractCursor {
//定义管理器
DataSetObservable mDataSetObservable = new DataSetObservable();
ContentObservable mContentObservable = new ContentObservable();
//注册和卸载两类观察者
public void registerContentObserver(ContentObserver observer) {
mContentObservable.registerObserver(observer);
}
public void unregisterContentObserver(ContentObserver observer) {
// cursor will unregister all observers when it close
if (!mClosed) {
mContentObservable.unregisterObserver(observer);
}
}
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
//2类通知方法
protected void onChange(boolean selfChange) {
synchronized (mSelfObserverLock) {
mContentObservable.dispatchChange(selfChange);
if (mNotifyUri != null && selfChange) {
mContentResolver.notifyChange(mNotifyUri, mSelfObserver);
}
}
}
protected void notifyDataSetChange() {
mDataSetObservable.notifyChanged();
}
}
再看看Observable
public abstract class Observable {
/**
* 观察者列表
*/
protected final ArrayList mObservers = new ArrayList();
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObservers.add(observer);
}
}
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
和
public class DataSetObservable extends Observable {
/**
* 数据发生变化时,通知所有的观察者
*/
public void notifyChanged() {
synchronized(mObservers) {
for (DataSetObserver observer : mObservers) {
observer.onChanged();
}
}
}
//... ... (其他方法)
}
观察者DataSetObserver类是一个抽象类:
public abstract class DataSetObserver {
public void onChanged() {
// Do nothing
}
}
所以我们具体看它的子类:
public class AlphabetIndexer extends DataSetObserver{
/*
* @hide 被android系统隐藏起来了
*/
@Override
public void onChanged() {
//观察到数据变化,观察者做自己该做的事情
super.onChanged();
mAlphaMap.clear();
}
}
ContentObserver也是类似。
4.效果
(1).行为型模式
(2).目标和观察者间的抽象耦合(经典实现)。
(3).支持广播通信(相信这点android开发者看到后应该有启发吧)。
(4).注意意外的更新,这也是观察者更新进行管理的原因之一。
代理模式请参看:
http://blog.csdn.net/qq_27489007/article/details/53426428
命令模式,在.net,java平台的事件机制用的非常多,几乎每天都与之打交道。
android中对我印象最深的就是多线程多进程的环境,所以必然大量使用到Runbable,Thread,其实用的就是最简单的命令模式。
命令模式,Command Pattern,把请求封装为一个对象,多么巧妙的一个说法啊。
1.意图
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
热门词汇:动作 事物 请求封装 排队 打包 异步
2.结构
Command接口提供了Execute方法,客户端通过Invoker调用命令操作来调用Recriver,绕了一大圈,
但是却把具体对Receiver的操作请求封装在具体的命令中,是客户端对recriver的操作清晰简明。
但是在实际项目中,我们常常忽略Receiver,而把命令对象的目标对象直接设置为子类自己的成员变
量或者作为execute()方法的临时变量。
以Android中的Runnable(在java.lang包下)为例,我们画出UML结构图如下:
想不到我们天天写的代码无意识中就是用到了命令模式,所谓模式,就是无所不在。
3.代码
命令接口Runnable定义如下:
public interface Runnable {
public abstract void run();
}
调用者Thread简化版代码:
//命令模式这里不需要继承Runnable接口,但是这里考虑到实际情况,比如方便性等,继承了Runnable接口,实现了run方法,这个是Thread自身的运行run的方法
class Thread implements Runnable {
private Runnable target;
public Thread(Runnable target) {
this.target = target;
}
public synchronized void start() {
if (threadStatus != 0 || this != me)
throw new IllegalThreadStateException();
group.add(this);
start0();//这个是本地方法,调用run方法
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
//可选
public void run() {
if (target != null) {
target.run();
}
}
}
客户端只需要new Thread(new Runnable(){}).start()就开始执行相关的一系列的请求,这些请求大部分都是实现Runnable接口的匿名类。
4.效果
(1).行为型模式;
(2).将调用对象的操作和知道如何实现该操作的对象解耦;
(3).多个命令可以装配成一个复合命令;
(4).增加新的命令很容易。
Android常用8种设计模式(一)
Android常用8种设计模式(三)