Android设计模式之观察者模式

上一篇讲述了单例模式,简单,理解起来也不会太困难,接下来继续讲一下观察者模式

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

看定义,依然会有点懵逼,待会还是看实际代码吧。。。

 

观察者模式的特点:

1.它实现了 Subject 和 Observer 之间的松耦合,Subject只知道观察者实现了 Observer 接口,主题不需要知道具体的类是谁、做了些什么或其他任何细节。

2.任何时候我们都可以增加新的观察者。

3.因为主题唯一依赖的东西是一个实现Observer 接口的对象列表,所以我们可以随时增加观察者,同样的,也可以在任何时候删除观察者,当然更不用去关心观察者的类型,只要实现了Observer接口即可,Subject 最后只会发通知给实现了 Observer 接口的观察者。

4.Subject 和 Observer 之间实现松耦合之后,双方代码的修改都不会影响到另外一方,当然前提是双方得遵守接口的规范。

 

适用环境:

1) 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
2) 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
3) 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
 
下面,通过代码来深入理解吧,
观察者模式实现主要分四步:
第一步:创建目标
第二步:创建观察者
第三步:注册观察者
第四步:订阅目标信息发生改变或更新
 
简略看一下类图:

 

 首先第一个,创建一个目标父类Subject

 1 /*
 2 * 创  建  者: ouyangshengduo
 3 * 创建时间: 2017年3月31日
 4 * 文件名称: Subject.java
 5 * 版权信息: 2017 Edan. All rights reserved. 
 6 * 文件描述: 观察者模式中的目标父类,管理观察者
 7 */
 8 package com.oysd.model.observer;
 9 
10 import java.util.ArrayList;
11 import java.util.List;
12 
13 public class Subject {
14     
15     /**
16      * 声明并初始化管理观察者的集合
17      */
18     private List<Observer> observers = new ArrayList<Observer>();
19     
20     
21     /**
22      * 注册观察者方法
23      * @param observer
24      */
25     public void attach(Observer observer){
26         observers.add(observer);
27     }
28     
29     /**
30      * 移除特定的观察者
31      * @param observer
32      */
33     public void detach(Observer observer){
34         observers.remove(observer);
35     }
36     
37     /**
38      * 通知所有注册的观察者
39      */
40     public void notifyObserver(){
41         for(Observer observer : observers){
42             observer.update(this);
43         }
44     }
45     
46     
47 
48 }

创建观察者的接口Observer

 1 /*
 2 * 创  建  者: ouyangshengduo
 3 * 创建时间: 2017年3月31日
 4 * 文件名称: Observer.java
 5 * 版权信息: 2017 Edan. All rights reserved. 
 6 * 文件描述: 观察者接口
 7 */
 8 package com.oysd.model.observer;
 9 
10 public interface Observer {
11 
12     /**
13      * 订阅信息更新通知
14      * @param subject
15      */
16     public void update(Subject subject);
17 }

创建具体目标对象ConcreteSubject

 1 /*
 2 * 创  建  者: ouyangshengduo
 3 * 创建时间: 2017年3月31日
 4 * 文件名称: ConcreteSubject.java
 5 * 版权信息: 2017 Edan. All rights reserved. 
 6 * 文件描述: 具体的目标类
 7 */
 8 package com.oysd.model.observer;
 9 
10 public class ConcreteSubject extends Subject {
11     
12     //订阅信息
13     private String notifyInfo;
14 
15     public String getNotifyInfo() {
16         return notifyInfo;
17     }
18 
19     
20     //订阅信息的更改
21     public void setNotifyInfo(String notifyInfo) {
22         this.notifyInfo = notifyInfo;
23         
24         this.notifyObserver();
25     }
26     
27     
28 
29 }

创建具体的观察者对象ConcreteObserver

 1 /*
 2 * 创  建  者: ouyangshengduo
 3 * 创建时间: 2017年3月31日
 4 * 文件名称: ConcreteObserver.java
 5 * 版权信息: 2017 Edan. All rights reserved. 
 6 * 文件描述: 具体的观察者对象
 7 */
 8 package com.oysd.model.observer;
 9 
10 public class ConcreteObserver implements Observer {
11     //观察者名字
12     private String observerName;
13     
14     //观察者订阅信息
15     private String notifyInfo;
16     
17     //观察者处理信息
18     private String excuteInfo;
19     
20 
21     @Override
22     public void update(Subject subject) {
23         // TODO Auto-generated method stub
24 
25         notifyInfo = ((ConcreteSubject) subject).getNotifyInfo();
26         System.out.println(observerName + "收到" + notifyInfo + "," + excuteInfo);
27 
28     }
29 
30 
31     public String getObserverName() {
32         return observerName;
33     }
34 
35 
36     public void setObserverName(String observerName) {
37         this.observerName = observerName;
38     }
39 
40 
41     public String getNotifyInfo() {
42         return notifyInfo;
43     }
44 
45 
46     public void setNotifyInfo(String notifyInfo) {
47         this.notifyInfo = notifyInfo;
48     }
49 
50 
51     public String getExcuteInfo() {
52         return excuteInfo;
53     }
54 
55 
56     public void setExcuteInfo(String excuteInfo) {
57         this.excuteInfo = excuteInfo;
58     }
59     
60     
61 
62 }

新建一个测试类Client

 1 /*
 2 * 创  建  者: ouyangshengduo
 3 * 创建时间: 2017年3月31日
 4 * 文件名称: Client.java
 5 * 版权信息: 2017 Edan. All rights reserved. 
 6 * 文件描述: 
 7 */
 8 package com.oysd.model.observer;
 9 
10 public class Client {
11 
12     public static void main(String[] args) {
13         // TODO Auto-generated method stub
14 
15         
16         //第一步:创建目标实例
17         ConcreteSubject subject = new ConcreteSubject();
18         
19         //第二步:创建观察者实例
20         ConcreteObserver observer1 = new ConcreteObserver();
21         observer1.setObserverName("observer1");
22         observer1.setExcuteInfo("observer1处理信息");
23         
24         ConcreteObserver observer2 = new ConcreteObserver();
25         observer2.setObserverName("observer2");
26         observer2.setExcuteInfo("observer2处理信息");
27         
28         //第三步:注册观察者
29         subject.attach(observer1);
30         subject.attach(observer2);
31         
32         //第四步:订阅信息发生更改或更新
33         subject.setNotifyInfo("订阅信息发生更改");
34     }
35 
36 }

 

运行结果:

1 observer1收到订阅信息发生更改,observer1 处理信息
2 observer2收到订阅信息发生更改,observer2处理信息

 

综上,观察者模式的通用写法就写完了

观察者模式又分推/拉模式,通用写法是拉模式

所谓拉模式就是目标类不知道观察者想要什么信息,就整个都获取,然后想要什么 就拿什么,

observer.update(this);就是把这个对象都返回

而推模式,就是目标类知道观察者想要什么信息,就直接发送特定的信息,那么就更改传入参数,就可以由拉模式改成推模式

observer.update(para);

引入观察者模式的时候,使用者要充分考虑运行环境后,实际情况实际分析,也不能盲目使用。

 

posted @ 2017-03-31 17:32  欧阳生朵  阅读(362)  评论(0编辑  收藏  举报