设计模式之观察者模式---Observer Pattern
来源:互联网 发布:caffe loss大小 编辑:程序博客网 时间:2024/05/22 09:04
模式的介绍
模式的定义
观察者模式(Observer Pattern)也叫发布订阅模式(Publish\subscribe),定义如下:
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.
定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
模式的使用场景
- 关联行为场景
- 事件多级触发场景
- 跨系统的消息交换场景,如消息队列的处理机制
UML类图
角色介绍
- Observer 观察者
定义了观察者更新的操作方法update
- Subject 被观察者
定义了观察者的注册,注销接口和被观察者变化的通知接口
- ConcreteObserver 具体的观察者
- ConcreteSubject 具体的被观察者
主要是实现了注册,注销和通知数据更新的三个接口,其中的一个关键变量-List concreteObserver,这个变量主要是对所有的观察者进行管理,当数据改变时,遍历所有的观察者,进行相对应的操作。
模式的简单实现
抽象观察者类 Observer :
定义了一个更新操作的接口
public interface Observer { public void update(); }
具体的观察者 ConcreteObserver:
实现了update更新操作
public class ConcreteObserver implements Observer{ @Override public void update() { // TODO Auto-generated method stub System.out.println("we receive message, do update!"); }}
抽象被观察者类 Subject :
关键是定义注册(register),反注册(unregister),内容改变的通知(notifyObservers)三个方法和观察者的集合变量(Vector observers)。
import java.util.Vector;public abstract class Subject { private Vector<Observer> observers = new Vector<Observer>(); public void register(Observer observer){ if(!observers.contains(observer)){ observers.add(observer); } } public void unregister(Observer observer){ if(observers.contains(observer)){ observers.remove(observer); } } public void notifyObservers(){ for(Observer o:observers){ o.update(); } }}
具体观察者 ConcreteSubject :
public class ConcreteSubject extends Subject{ public void doSomething(){ super.notifyObservers(); }}
Main方法:
public static void main(String[] args) { ConcreteSubject concreteSubject = new ConcreteSubject(); Observer observer = new ConcreteObserver(); concreteSubject.register(observer); concreteSubject.doSomething(); }
程序输出:
we receive message, do update!
模式的综合样例
对于学校的学生来说,上课铃声响后,学生要上课听讲,老师的上课教书,这是非常熟悉的。其实,这就是一个非常经典的观察者模式(一对多)。
先来看一下我们的类图:
我们定义一个观察者的接口Observer:
public interface Observer { public void update();}
然后对应的定义二个观察者学生(Student),老师(Teacher),实现其Observer接口。
public class Student implements Observer { @Override public void update() { // TODO Auto-generated method stub System.out.println("上课铃声响了,又要听这个老师xxxxxxxx…………"); }}
public class Teacher implements Observer{ @Override public void update() { // TODO Auto-generated method stub System.out.println("上课铃声响了,又要给这帮孩子…………xxxxxxxx"); }}
我们再定义被观察者的接口Observable :
public interface Observable { public void register(Observer oberver); public void unregister(Observer oberver); public void notifyDate();}
再综合单例模式定义一个被观察者铃声类Ringtone ,实现Observable 接口:
import java.util.Vector;public class Ringtone implements Observable{ private static Ringtone ringtone = new Ringtone(); public static Vector<Observer> observers = new Vector<Observer>(); private Ringtone(){ } public static final Ringtone getRingtoneSinglone(){ return ringtone; } @Override public void register(Observer oberver) { // TODO Auto-generated method stub if(!observers.contains(oberver)){ observers.add(oberver); } } @Override public void unregister(Observer oberver) { // TODO Auto-generated method stub if(observers.contains(oberver)){ observers.remove(oberver); } } @Override public void notifyDate() { // TODO Auto-generated method stub for(Observer observer:observers){ observer.update(); } } public void ring(){ System.out.println("上课铃声响了!!"); notifyDate(); }}
Main:
public static void main(String[] args) { // TODO Auto-generated method stub Ringtone ringtone = Ringtone.getRingtoneSinglone(); Observer student = new Student(); Observer teacher = new Teacher(); ringtone.register(teacher); ringtone.register(student); ringtone.ring();}
程序输出:
上课铃声响了!!上课铃声响了,又要给这帮孩子…………xxxxxxxx上课铃声响了,又要听这个老师xxxxxxxx…………
模式的优缺点
优点
- 观察者和被观察者之间是抽象耦合
- 建立一套触发机制
缺点
观察者模式需要考虑开发效率和运行效率。一个被观察者,多个观察者,开发和调试比较复杂,而且java中消息的通知默认是顺序执行,一个观察者卡壳,会影响整体的执行效率。在这种情况下,一般考虑异步的方式。
多级触发的效率更是让人担忧,大家设计时要注意考虑。
Android源码中的模式实现
BroadcastReceiver
在android开发时,我们经常定义一个新的广播(观察者),
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String msg = intent.getStringExtra("msg"); .............. } }
然后注册,有二种方式:
(1)静态注册
在androidManifest.xml中注册:
<receiver android:name=".MyReceiver"> <intent-filter> <action android:name="android.intent.action.MY_BROADCAST"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>
(2)代码动态注册
MyReceiver receiver = new MyReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.MY_BROADCAST"); registerReceiver(receiver, filter);
对应的反注册的方式:
protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); }
当我们发送对应的Intent时,
Intent intent = new Intent("android.intent.action.MY_BROADCAST"); intent.putExtra("msg", "hello receiver."); sendBroadcast(intent);
对应的MyReceiver会执行onReceive方法,更新对应的操作。
从上面的使用过程,我们可以清楚的看到:
MyReceiver做为具体的观察者(ConcreteObserver),我们只需要实现其onReceive的更新方法。
BroadcastReceiver 做为抽象观察者(Observer)。
在android源码中:
./frameworks/base/core/java/android/content/BroadcastReceiver.java
看到:
//抽象类 BroadcastReceiver,做为Observerpublic abstract class BroadcastReceiver { ............ //定义抽象更新方法onReceive public abstract void onReceive(Context context, Intent intent); ............}
在当前Context中,例如Activity,相当于具体的被观察者类,我们调用:
registerReceiver方法注册
unregisterReceiver方法反注册
sendBroadcast方法通知被观察者已经改变,观察者调用onReceive方法更新。
Activity的类:
Context类相当于Subject 抽象的被观察者.
在android的源码中:
./frameworks/base/core/java/android/content/Context.java
关键方法:
//抽象被观察者类 Contextpublic abstract class Context {............. //注册方法 registerReceiver public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,IntentFilter filter); public abstract Intent registerReceiver(BroadcastReceiver receiver,IntentFilter filter, @Nullable String broadcastPermission,@Nullable Handler scheduler); //反注册方法 unregisterReceiver public abstract void unregisterReceiver(BroadcastReceiver receiver); //通知被观察者改变的方法 sendBroadcast public abstract void sendBroadcast(Intent intent); public abstract void sendBroadcast(Intent intent, @Nullable String receiverPermission); public abstract void sendBroadcast(Intent intent,String receiverPermission, int appOp);...............}
中间类ContextWrapper :
./frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context { Context mBase; //构造方法 public ContextWrapper(Context base) { mBase = base; }.......... //注册方法 registerReceiver public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); } public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return mBase.registerReceiver(receiver,filter,broadcastPermission,scheduler); } /** @hide */ @Override public Intent registerReceiverAsUser( BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { return mBase.registerReceiverAsUser(receiver, user,filter, broadcastPermission,scheduler); } //反注册方法 unregisterReceiver @Override public void unregisterReceiver(BroadcastReceiver receiver) { mBase.unregisterReceiver(receiver); } //通知被观察者改变的方法 sendBroadcast @Override public void sendBroadcast(Intent intent) { mBase.sendBroadcast(intent); } @Override public void sendBroadcast(Intent intent, String receiverPermission) { mBase.sendBroadcast(intent, receiverPermission); } /** @hide */ @Override public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { mBase.sendBroadcast(intent, receiverPermission,appOp); } ...............}
从代码来看,ContextWrapper 类实现了Conext类,在对应的重写方法中,只是调用了mBase变量的对应方法。
那么实现registerReceiver,unregisterReceiver,sendBroadcast三个方法的是类ContextImpl
./frameworks/base/core/java/android/app/ContextImpl.java
/** * Common implementation of Context API, which provides the base * context object for Activity and other application components. */class ContextImpl extends Context {................ //实现注册方法 registerReceiver @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null, null); } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext()); } @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, user.getIdentifier(), filter, broadcastPermission, scheduler, getOuterContext()); } private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { IIntentReceiver rd = null; if (receiver != null) { if (mPackageInfo != null && context != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } else { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher( receiver, context, scheduler, null, true).getIIntentReceiver(); } } try { return ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); } catch (RemoteException e) { return null; } } //反注册方法 unregisterReceiver @Override public void unregisterReceiver(BroadcastReceiver receiver) { if (mPackageInfo != null) { IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher( getOuterContext(), receiver); try { ActivityManagerNative.getDefault().unregisterReceiver(rd); } catch (RemoteException e) { } } else { throw new RuntimeException("Not supported in system context"); } } //通知被观察者改变的方法 sendBroadcast @Override public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false, getUserId()); } catch (RemoteException e) { } } @Override public void sendBroadcast(Intent intent, String receiverPermission) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, false, false, getUserId()); } catch (RemoteException e) { } } @Override public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermission, appOp, false, false, getUserId()); } catch (RemoteException e) { } }................}
可以看到ContextImpl实现registerReceiver,unregisterReceiver,sendBroadcast这三个方法是依靠:
//注册ActivityManagerNative.getDefault().registerReceiver//反注册ActivityManagerNative.getDefault().unregisterReceiver(rd)//广播ActivityManagerNative.getDefault().broadcastIntent
我们查看ActivityManagerNative类:
./frameworks/base/core/java/android/app/ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager{................. /** * Retrieve the system's default/global activity manager. * 返回一个IActivityManager */ static public IActivityManager getDefault() { return gDefault.get(); }................. //通过IBinder ,返回IActivityManager private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } return am; } }; //注册 public Intent registerReceiver(IApplicationThread caller, String packageName, IIntentReceiver receiver, IntentFilter filter, String perm, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeString(packageName); data.writeStrongBinder(receiver != null ? receiver.asBinder() : null); filter.writeToParcel(data, 0); data.writeString(perm); data.writeInt(userId); mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0); reply.readException(); Intent intent = null; int haveIntent = reply.readInt(); if (haveIntent != 0) { intent = Intent.CREATOR.createFromParcel(reply); } reply.recycle(); data.recycle(); return intent; } //反注册 public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(receiver.asBinder()); mRemote.transact(UNREGISTER_RECEIVER_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); } //广播 public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, int appOp, boolean serialized, boolean sticky, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null); data.writeInt(resultCode); data.writeString(resultData); data.writeBundle(map); data.writeString(requiredPermission); data.writeInt(appOp); data.writeInt(serialized ? 1 : 0); data.writeInt(sticky ? 1 : 0); data.writeInt(userId); mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0); reply.readException(); int res = reply.readInt(); reply.recycle(); data.recycle(); return res; }//关键变量,处理跨应用的数据传输 private IBinder mRemote;}
我们可以看出ActivityManagerNative类中registerReceiver,unregisterReceiver,broadcastIntent三个方法主要是调用mRemote.transact方法。mRemote是IBinder 变量,所以我们能理解,为什么广播是跨应用。
参考资料
(1).设计模式之禅—第22章 观察者模式
- 设计模式之观察者模式(Observer Pattern)
- 设计模式之观察者模式---Observer Pattern
- 观察者设计模式(Observer Pattern)
- 设计模式----行为型模式之观察者模式(Observer Pattern)
- 设计模式----行为型模式之观察者模式(Observer Pattern)
- 设计模式----行为型模式之观察者模式(Observer Pattern)
- 设计模式----行为型模式之观察者模式(Observer Pattern)
- 设计模式----行为型模式之观察者模式(Observer Pattern)
- 设计模式----行为型模式之观察者模式(Observer Pattern)
- 设计模式----行为型模式之观察者模式(Observer Pattern)
- 设计模式----行为型模式之观察者模式(Observer Pattern)
- 设计模式之观察者模式(Observer Pattern)(一)
- 设计模式之观察者模式(Observer Pattern)(二)
- 设计模式系列之三:观察者模式(Observer Pattern)
- Net设计模式实例之观察者模式(Observer Pattern)
- 设计模式之四 观察者模式(Observer Pattern)
- 设计模式之观察者模式(Observer Pattern)
- Java 设计模式之观察者模式(Observer pattern)
- 3、下载与安装Eclipse
- mView has no focus+DecorView setVisiblity: visibility = 4+Finishing stop of ActivityRecord
- c++连接SQL server2005
- C++中的SFINAE
- C++实现屏幕截图(全屏截图)
- 设计模式之观察者模式---Observer Pattern
- Codevs 1065 01字符串
- 带碰撞检测的摄像机
- 杭电acm--2052
- [leetcode-284]Peeking Iterator(java)
- 3D GAME PROGRAMMING WITH DIRECTX11(4)
- Lombok -- 简化你的Java编码 (JDK6+)
- 【UI初级------连载七】标签控制器
- HDU 1698 Just a Hook