设计模式-观察者模式(Observer Pattern)

观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

观察者模式在实现时,有两种方式,一种是推(push),一种是拉(pull)。

一直在用,却不知道什么是观察者模式。看到一篇文章,关于观察者模式的,说白了就是一个对象(被观察者)持有一堆对象(观察者)的引用,这些引用都放在一个列表中,当被观察者的状态改变时,就调用引用(观察者)的 update() 方法,让所有的观察者知道被观察者的状态改变了,然后自己也跟着变化。

其中关键点:

1. 一对多的关系,一个被观察者(object),一个或者多个观察者(observer)

2. 被观察者持有每个观察者的引用

3. 被观察者有注册和取消注册的方法

4. 在被观察者的类中,用列表存放观察者的引用

5. 当被观察者的状态改变时,调用相关的 notify() 方法,在 notify() 方法中调用每个观察者的 update() 方法来让观察者知道该事件。

自己撸了一段代码:(使用的是交通灯的案例,

1. 交通灯是被观察者,汽车是观察者

2. 当白天的时候需要看红绿灯,交通灯状态为绿色时,汽车行驶,交通灯状态为红色时,汽车等待

3. 当凌晨12点到4点的时候,不需要看红绿灯,可以*通过,这个时候交通灯的红绿灯就对汽车不起作用了。)

被观察者(TrafficLight)

 1 public class TrafficLight {
 2     private static final String TAG = "TrafficLight";
 3     private TrafficLightStatus defaultStatus = TrafficLightStatus.GREEN;
 4     private List<ICar> observerList = new ArrayList<>();
 5 
 6     public TrafficLightStatus getLightStatus() {
 7         return defaultStatus;
 8     }
 9 
10     public void setTrafficLightStatus(TrafficLightStatus status) {
11         defaultStatus = status;
12     }
13 
14     public void notifyStatusChange() {
15         if (observerList.size() > 0) {
16             for (int i = 0; i < observerList.size(); i++) {
17                 if (defaultStatus == TrafficLightStatus.GREEN) {
18                     observerList.get(i).move();
19                 } else {
20                     observerList.get(i).stop();
21                 }
22             }
23         }
24     }
25 
26     public void registerTrafficLight(ICar car) {
27         if (!observerList.contains(car)) {
28             observerList.add(car);
29         }
30     }
31 
32     public void unRegisterTrafficLight(ICar car) {
33         if (observerList.contains(car))
34             observerList.remove(car);
35     }
36 }

观察者(ICar)

1 public interface ICar {
2     void move();
3     void stop();
4 }

观察者的实现类(ToytaCar...)

 1 public class ToytaCar implements ICar {
 2     private static final String TAG = "ToytaCar";
 3 
 4     @Override
 5     public void move() {
 6         Log.e(TAG, "ToytaCar,绿灯,行驶");
 7     }
 8 
 9     @Override
10     public void stop() {
11         Log.e(TAG, "ToytaCar,红灯,等待");
12     }
13 }

MainActivity,4个 Button,分别是注册,取消注册,状态改变(绿灯,红灯)

 1 public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 2     private List<ICar> carList = new ArrayList<>();
 3     Button btnRedLight, btnGreenLight, btnFreeLight, btnLimitLight; 6     TrafficLight trafficLight;
 7     ICar toytaCar, nissanCar, mazdaCar, hondaCar, fordCar, bydCar, bmwCar, audiCar;
 8 
 9     @Override
10     protected void onCreate(Bundle savedInstanceState) {
11         super.onCreate(savedInstanceState);
12         setContentView(R.layout.activity_main);
23         btnRedLight = (Button) findViewById(R.id.btn_red_light);
24         btnGreenLight = (Button) findViewById(R.id.btn_green_light);
25         btnFreeLight = (Button) findViewById(R.id.btn_free_light);
26         btnLimitLight = (Button) findViewById(R.id.btn_limit_light);
27         btnRedLight.setOnClickListener(this);
28         btnGreenLight.setOnClickListener(this);
29         btnFreeLight.setOnClickListener(this);
30         btnLimitLight.setOnClickListener(this);
31         trafficLight = new TrafficLight();
32         toytaCar = new ToytaCar();
33         nissanCar = new NissanCar();
34         mazdaCar = new MazdaCar();
35         hondaCar = new HondaCar();
36         fordCar = new FordCar();
37         bydCar = new BYDCar();
38         bmwCar = new BWMCar();
39         audiCar = new AudiCar();
40         carList.add(toytaCar);
41         carList.add(nissanCar);
42         carList.add(mazdaCar);
43         carList.add(hondaCar);
44         carList.add(bydCar);
45         carList.add(bmwCar);
46         carList.add(audiCar);
47         carList.add(fordCar);49     }
50 
51     @Override
52     public void onClick(View v) {
53         switch (v.getId()) {
54             case R.id.btn_green_light:
55                 trafficLight.setTrafficLightStatus(TrafficLightStatus.GREEN);
56                 trafficLight.notifyStatusChange();
57                 break;
58             case R.id.btn_red_light:
59                 trafficLight.setTrafficLightStatus(TrafficLightStatus.RED);
60                 trafficLight.notifyStatusChange();
61                 break;
62             case R.id.btn_free_light:
63                 for (int i = 0; i < carList.size(); i++) {
64                     trafficLight.unRegisterTrafficLight(carList.get(i));
65                 }
66                 break;
67             case R.id.btn_limit_light:
68                 for (int i = 0; i < carList.size(); i++) {
69                     trafficLight.registerTrafficLight(carList.get(i));
70                 }
71                 break;
72             default:
73                 break;
74         }
75     }
76 }

log 输出:

1. 当点击按钮-看红绿灯(注册),点击红绿灯按钮就可以调用 ICar 的 move() 或者 stop() 方法,打印出来日志

 1 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/ToytaCar: ToytaCar,红灯,等待
 2 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/NissanCar: NissanCar,红灯,等待
 3 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/MazdaCar: MazdaCar,红灯,等待
 4 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/HondaCar: HondaCar,红灯,等待
 5 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/BYDCar: BYDCar,红灯,等待
 6 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/BWMCar: BWMCar,红灯,等待
 7 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/AudiCar: AudiCar,红灯,等待
 8 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/FordCar: FordCar,红灯,等待
 9 01-09 22:32:56.844 6900-6900/cc.lijingbo.pattern_observer E/ToytaCar: ToytaCar,绿灯,行驶
10 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/NissanCar: NissanCar,绿灯,行驶
11 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/MazdaCar: MazdaCar,绿灯,行驶
12 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/HondaCar: HondaCar,绿灯,行驶
13 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/BYDCar: BYDCar,绿灯,行驶
14 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/BWMCar: BWMCar,绿灯,行驶
15 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/AudiCar: AudiCar,绿灯,行驶
16 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/FordCar: FordCar,绿灯,行驶

2. 当点击按钮-*通过(取消注册),这个时候点击红绿灯按钮不起作用,不打印日志

 

  

参考:

《对象间的联动——观察者模式》:http://blog.csdn.net/lovelion/article/details/7720232

《面试被问设计模式?不要怕看这里:观察者模式》:http://mp.weixin.qq.com/s/pH7ifcOPzVxdrAIk4W8HiQ

《设计模式之观察者模式》:http://www.jianshu.com/p/d55ee6e83d66#