设计模式之观察者模式---Observer Pattern

模式的介绍

模式的定义

观察者模式(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 Pattern_第1张图片

角色介绍

  • 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 observers = new Vector();

    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 Pattern_第2张图片

我们定义一个观察者的接口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 observers = new Vector();

    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,做为Observer
public abstract class BroadcastReceiver {
    ............
    //定义抽象更新方法onReceive
    public abstract void onReceive(Context context, Intent intent);
    ............
}

在当前Context中,例如Activity,相当于具体的被观察者类,我们调用:
registerReceiver方法注册
unregisterReceiver方法反注册
sendBroadcast方法通知被观察者已经改变,观察者调用onReceive方法更新。

Activity的类:
设计模式之观察者模式---Observer Pattern_第3张图片

Context类相当于Subject 抽象的被观察者.
在android的源码中:

./frameworks/base/core/java/android/content/Context.java

关键方法:

//抽象被观察者类 Context
public 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章 观察者模式

你可能感兴趣的:(设计模式之样例篇,设计模式之android)