代码改变世界

观察者模式

2019-03-06 10:16  剑动情缥缈  阅读(169)  评论(0编辑  收藏  举报

1.概念

  • 定义了一种一对多的依赖关系,让多个观察者可以监控一个主题对象,当主题对象发生改变,会通知所有的观察者,让他们能够自动更新自己
  • UML

  

  • 角色

  1)抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。

  2)具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。

  3)抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。

  4)具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。

  • 推模型与拉模型

  1)推模型:主题将信息推送给观察者,如下代码所示

  2)拉模型:主题通知观察者,让观察者自己从主题获取信息

2.代码

 1 package com.chengjie;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 //主题
 7 abstract class Subject {
 8     private List<Observer> list = new ArrayList<Observer>();
 9 
10     public void attach(Observer o) {
11         list.add(o);
12     }
13 
14     public void detach(Observer o) {
15         list.remove(o);
16     }
17 
18     public void notifyAllObservers(String state) {
19         for (Observer o : list) {
20             o.update(state);
21         }
22     }
23 }
24 
25 class RealSubject extends Subject {
26     public String getState() {
27         return state;
28     }
29 
30     private String state;
31 
32     public void change(String newState) {
33         state = newState;
34         notifyAllObservers(newState);
35     }
36 }
37 
38 interface Observer {
39     void update(String state);
40 }
41 
42 class RealObserver implements Observer {
43     private String observerState;
44 
45     @Override
46     public void update(String state) {
47         observerState = state;
48         System.out.println("RealObserver state:" + observerState);
49     }
50 }
51 
52 public class TestObserver {
53     public static void main(String[] args) {
54         //新建主题
55         RealSubject subject = new RealSubject();
56 
57         //新建观察者
58         Observer observer = new RealObserver();
59 
60         //将观察者注册进主题
61         subject.attach(observer);
62 
63         //改变主题状态
64         subject.change("a new state");
65     }
66 }
View Code

3.优点

  • 观察者与主题是解耦的,可以动态添加观察者与删除观察者

4.缺点

  • 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃

5.使用场景

  • 一个对象改变需要通知其他对象,而不知道具体对象是谁
  • 一个抽象模型改变依赖于另一个模型,将这些方面封装在独立的对象使他们能够独立改变和复用
  • 需要在系统中创建一个触发链,A触发B,B触发C

  在JAVA语言的java.util库里面,提供了一个Observable类以及一个Observer接口,构成JAVA语言对观察者模式的支持。

6.参考

  https://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html

  http://www.runoob.com/design-pattern/observer-pattern.html