观察者模式(行为型)

来源:互联网 发布:虚拟拍照软件下载 编辑:程序博客网 时间:2024/06/06 08:42

  在软件系统中经常会有这样的需求:如果一个对象的状态发生改变,某些与它相关的对象也要随之做出相应的变化。举个例子,要设计一个右键菜单的功能,只要在软件的有效区域内点击鼠标右键,就会弹出一个菜单;再举一个现实生活中的例子,你的一个朋友存了你的手机号码,有一天你把号码换了,你是不是要把换号码的消息通知你的朋友,并且把新号码也告诉他。
  上面的例子有一个关键的地方,就是一个对象要时刻监听着另一个对象,只要它的状态已发送改变,自己要随之做出相应的行动。

定义:定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,所有依赖于它的对象都会得到通知并自动更新。

结构

  • 被观察者:管理观察者并通知观察者,必须能够动态的增加、取消观察者,一般为抽象类
  • 具体的被观察者:便于扩展,被观察者的具体实现
  • 观察者:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己
  • 具体的观察者:观察者的具体实现,定义被观察者对象状态发送变化时索要处理的逻辑

用途

  • 当抽象个体有两个互相依赖的层面时。封装这些层面在单独的对象内将可允许程序员单独地去变更与重复使用这些对象,而不产生两者之间的交互问题
  • 当其中一个对象的变更会影响到其他对象,却又不知道多少对象必须被同时变更时
  • 当对象应该有能力通知其他对象,又不应该知道其他对象的实做细节时

UML
这里写图片描述

观察者模式分为拉模型和推模型两种方式,下面分别对这两种方式的实现进行介绍:
推模型

public interface Observer {    void update(String updateContent);}public class ConcreteObserver implements Observer{    @Override    public void update(String updateContent) {        System.out.println(updateContent);    }}
public abstract class Subject {    List<Observer> list = new ArrayList<Observer>();    String updateContent;    public void register(Observer observer){        list.add(observer);    }    public void cancel(Observer observer){        list.remove(observer);    }    public void notifyObservers(){        for(Observer o:list){            o.update(updateContent);        }    }    public abstract void change();}public class ConcreteSubject extends Subject{    @Override    public void change() {        this.updateContent = "我改变了";        notifyObservers();    }}

拉模型

public interface Observer {    void update(Subject subject);}public class ConcreteObserver implements Observer{    @Override    public void update(Subject subject) {        // TODO Auto-generated method stub        System.out.println(subject.updateContent);    }}
public abstract class Subject {    List<Observer> list = new ArrayList<Observer>();    public String updateContent;    public void register(Observer observer){        list.add(observer);    }    public void cancel(Observer observer){        list.remove(observer);    }    public void notifyObservers(){        for(Observer o:list){            o.update(this);        }    }    public abstract void change();}public class ConcreteSubject extends Subject{    @Override    public void change() {        this.updateContent= "我改变了";        notifyObservers();    }}

测试类

public class Test {    public static void main(String[] args){        Subject s = new ConcreteSubject();        Observer o = new ConcreteObserver();        s.register(o);        s.change();    }}

  从代码可以看出,推磨型与拉模型的区别就是通知更新时传给观察者的参数不用。推磨型是假定被观察者知道观察者需要的数据;拉模型则是不知道观察者需要什么数据,直接把自身传递给观察,让观察者自己去按需要取值(所以读者是不是都希望碰到这样的被观察者呢,**和谐**)。一般情况下都是用拉模型比较多,因为推模型观察者的update方法是按需要定义参数的,无法兼顾到没有考虑到的情况,这就意味者出现新情况时,就要提供新的update方法,甚至得重新实现观察者模式,使得观察者对象难以复用;拉模型就不会出现这种情况,update方法的参数是被观察者本身,基本上是被观察者能传递的最大数据集合了(把自己都给你了,还想我怎样!!!),可以适应各种情况。
总结:观察者模式的执行要领,先要对观察者进行注册,被观察者发送变化时,遍历并通知所有观察者。


参考:https://zh.wikipedia.org/wiki/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F
   http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html

0 0
原创粉丝点击