设计模式之观察者模式

  对于观察者模式而言,肯定有观察者和被观察者之分。比如在一个目录下建立一个文件,这时系统会通知目录管理器增加目录,并通知磁盘减少空间,在这里,文件就是观察者,目录管理器和磁盘就是被观察者。

  观察者模式(Observer),区别于发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。观察者模式里,只有两个角色 —— 观察者 + 被观察者,而发布订阅模式里,却不仅仅只有发布者和订阅者两个角色,还有一个经常被我们忽略的 —— 经纪人Broker;观察者和被观察者,是松耦合的关系,发布者和订阅者是不存在耦合。UML结构图如下:

 

  其中,Subject类是主题,它把所有对观察者对象的引用文件存在了一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供了一个接口,可以增加和删除观察者对象;Observer类是抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己;ConcreteSubject类是具体主题,将有关状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知;ConcreteObserver是具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协同。

  1、主题Subject  

  首先定义一个观察者数组,并实现增、删及通知操作。它的职责很简单,就是定义谁能观察,谁不能观察,用Vector是线程同步的,比较安全,也可以使用ArrayList,是线程异步的,但不安全。

 1 public class Subject {
 2     //观察者数组
 3     private Vector<Observer> oVector = new Vector<>();
 4     //增加一个观察者
 5     public void addObserver(Observer observer) {
 6         this.oVector.add(observer);
 7     }
 8     //删除一个观察者
 9     public void deleteObserver(Observer observer) {
10         this.oVector.remove(observer);
11     }
12     //通知所有观察者
13     public void notifyObserver() {
14         for(Observer observer : this.oVector) {
15             observer.update();
16         }
17     }
18 }
主题

   2、抽象观察者Observer

  观察者一般是一个接口,每一个实现该接口的实现类都是具体观察者。

1 public interface Observer {
2      //更新
3      public void update();
4 }
抽象观察者

  3、具体主题

  继承Subject类,在这里实现具体业务,在具体项目中,该类会有很多变种。

1 public class ConcreteSubject extends Subject {
2     //具体业务
3     public void doSomething() {
4         //...
5         super.notifyObserver();
6     }
7 }
具体主题

  4、具体观察者

1 public class ConcreteObserver implements Observer {
2     @Override
3     public void update() {
4         System.out.println("收到消息,进行处理");
5     }
6 }
实现Observer接口
 1 public class Client {
 2     public static void main(String[] args) {
 3         //创建一个主题
 4         ConcreteSubject subject = new ConcreteSubject();
 5         //定义一个观察者
 6         Observer observer = new ConcreteObserver();
 7         //观察
 8         subject.addObserver(observer);
 9         //开始活动
10         subject.doSomething();
11     }
12 }
Demo

  注意:

  (1)一对多,一个对象状态改变,所有依赖对象都将得到通知。

  缺点:

    如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间

    如果观察者和观察目标间有循环依赖,可能导致系统崩溃

    没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的

posted on 2020-03-13 11:37  hdc520  阅读(139)  评论(0编辑  收藏  举报

导航