深入浅出设计模式之观察者设计模式

举例

先让我们看一个简单的现实生活中的观察者设计模式。
我们都知道老师与学生家长的关系
老师会把每次考试的成绩告诉家长(主题)
只要是老师所教的班级的学生的家长才能收到,别的班级的家长不能收到
当学生毕业后,学生家长就无法收到学生成绩
只要产生新的考试,家长才会收到消息

根据上述的例子:老师(主题)+学生家长(观察者)=观察者模式

下面就是观察者的总体模型。
这里写图片描述

定义

对象之间的一对多依赖,当一个对象改变状态是,他所对的依赖着都会收到通知并自动更新。

接口图:(这个图的例子不是上述例子,但是大致接口和类相似)
这里写图片描述

实现

上述的例子用代码实现:

//观察者借口
public interface Observer {
    //被通知
    void notified(String math,String english);
}
//主题借口
public interface Subject {
    //注册观察者
    void registerObserver(Observer o);
    //移除观察者
    void removeObserver(Observer o);
    //通知观察者
    void notifyObserver();
}

//观察者实现类
public class Parents implements Observer{

    //把家长注册到老师里
    public Parents(Subject sub) {
        sub.registerObserver(this);
    }
    //子类通知
    public void notified(String math,String english){
        System.out.println("接受到消息:"+"  "+math+"  "+english);
    }
}

import java.util.ArrayList;
import java.util.List;

//主题实现类
public class Teacher implements Subject{

    List<Observer> observers;
    String math,english;

    Teacher(){
        observers=new ArrayList<Observer>();
    }

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        if(observers.contains(o)){
            observers.remove(o);
        }
    }

    @Override
    public void notifyObserver() {
        for(Observer o:observers){
            o.notified(math,english);
        }
    }

    public void examine(String math,String english){
        this.math=math;
        this.english=english;
        notifyObserver();
    }

}

//测试类
public class Test {
    public static void main(String[] args) {
        //设置一个主题
        Teacher teacher = new Teacher();
        //加入一个观察者
        Parents parents=new Parents(teacher);

        //发送消息
        teacher.examine("math考试", "english考试");

    }

}

java内置的观察者模式:

在java.util 包下面的 Observer 接口 和 Observable类

java内置的观察者模式如何运作:
如何把对象变成观察者。
可观察者要如何送出通知。
观察者如何接收通知。

用java内置类实现例子。

import java.util.Observable;

//主题实现类
public class Teacher extends Observable{
    String math,english;

    public void examine(String math,String english){
        this.math=math;
        this.english=english;
        setChanged();
        notifyObservers();
    }

    public String getMath() {
        return math;
    }

    public String getEnglish() {
        return english;
    }
}


import java.util.Observable;
import java.util.Observer;

import javax.security.auth.Subject;

//观察者实现类
public class Parents implements Observer{

    //把家长注册到老师里
    public Parents(Observable observable) {
        observable.addObserver(this);
    }
    //子类通知
    public void notified(String math,String english){
        System.out.println("接受到消息:"+"  "+math+"  "+english);
    }
    @Override
    public void update(Observable o, Object arg) {
        Teacher teacher=(Teacher)o;
        notified(teacher.getMath(), teacher.getEnglish());

    }
}

大家如果还不明白上面自带的观察者是怎么1实现的可以看jdk的源码:

 public void notifyObservers(Object arg) {

        Object[] arrLocal;
        //同步
        synchronized (this) {
            //有一个changed属性判断状态是否改变
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        //和我们自己写的一样运行观察者队列的的update方法
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

缺点

java内置式实现类的缺点:
当然熟练的程序员可能已经会发现内置的观察者存在的问题,他把observable定义成类,因为java不支持单继承所以当我们要的类就不能继承别的类了。
observable中的setChanged方法都定义成了protected类型,所以除了子类外无法使用该函数

补充

观察者模式在关于目标(主题)角色、观察者角色通信的具体实现中,有两个版本。

1) 拉模式:目标角色在发生变化后,仅仅告诉观察者角色“我变化了”;观察者角色如果想要知道具体的变化细节,则就要自己从目标角色的接口中得到。拉模式是想要就主动表白获取。

2) 推模式:通知你发生变化的同时,通过一个参数将变化的细节传递到观察者角色中去。推模式是管你要不要,先给你啦。

这两种模式的使用,取决于系统设计时的需要。如果目标角色比较复杂,并且观察者角色进行更新时必须得到一些具体变化的信息,则“推模式”比较合适。如果目标角色比较简单,则“拉模式”就很合适啦。

观察者模式是非常常用的一个设计模式,再有些地方称它为设计模式的“皇后”,可想它的重要性。

在很多界面化编程中用到很多 事件监听机制http://blog.csdn.net/qq_25673113/article/details/53244571) ,这个就是典型的观察者模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值