阅读《Design pattern》-观察者模式

摘抄《设计模式》

意图:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
别名:
依赖(dependent),发布-订阅(publish-subscribe)
适用性:
在以下情况下可以使用观察者模式:
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中,以使它们可以各自独立地改变和复用。
对一个对象的改变需要同时改变其他对象,而不知道具体由多少对象需要改变。
一个对象必须通知其他对象,而他又不能假定其他对象是谁。换言之,你不希望这些对象紧密耦合的。
 
简单一句话:目标状态变化,触发所有观察者变化。
注意:一对多的关系,一个目标,多个观察者
 
目标提供一个方法:用于附上观察者,便于notify(通知)
观察者在初始时,关注(订阅)目标,并附上在目标上。释放时,取消关注(订阅),移除。
 

建立一个简单的观察者代码:
 1 /**
 2  * 观察者模式-目标接口
 3  */
 4 public interface ISubject {
 5     /**
 6      * 附上观察者
 7      * @param observer 观察者
 8      */
 9     public void attach(IObserver observer);
10 
11     /**
12      * 移除观察者
13      * @param observer 观察者
14      */
15     public void detach(IObserver observer);
16 
17     /**
18      * 通知所有观察者
19      */
20     public void notifyAllObserver();
21 }
 1 /**
 2  * 观察者模式-观察者接口
 3  */
 4 public interface IObserver {
 5     /**
 6      * 订阅目标
 7      * @param subject 目标
 8      */
 9     public void subscribe(ISubject subject);
10 
11     /**
12      * 取消订阅
13      */
14     public void unsubscribe();
15 
16     /**
17      * 业务更新
18      * @param subject 目标
19      */
20     public void update(ISubject subject);
21 }

上述是接口。下面定义父类基类

 1 /**
 2  * 目标基类/父类
 3  */
 4 public class BaseSubject implements ISubject {
 5     /**
 6      * 观察者列表
 7      */
 8     protected List<IObserver> observerList;
 9 
10     /**
11      * 构造函数
12      */
13     public BaseSubject() {
14         observerList = new ArrayList<>();
15     }
16 
17     @Override
18     public void attach(IObserver observer) {
19         if (observer != null) {
20             observerList.add(observer);
21         }
22     }
23 
24     @Override
25     public void detach(IObserver observer) {
26         if (observer != null) {
27             observerList.remove(observer);
28         }
29     }
30 
31     @Override
32     public void notifyAllObserver() {
33         for (IObserver item :
34                 observerList) {
35             item.update(this);
36         }
37     }
38 
39     @Override
40     protected void finalize() throws Throwable {
41         for (IObserver item :
42                 observerList) {
43             item.unsubscribe();
44         }
45         observerList.clear();
46         super.finalize();
47     }
48 }
 1 /**
 2  * 观察者基类/父类
 3  */
 4 public class BaseObserver implements IObserver {
 5     /**
 6      * 目标对象
 7      */
 8     protected ISubject subject;
 9 
10     /**
11      * 构造函数
12      */
13     public BaseObserver() {
14         this.subject = null;
15     }
16 
17     /**
18      * 构造函数
19      * @param subject 目标
20      */
21     public BaseObserver(ISubject subject) {
22         this.subject = null;
23         subscribe(subject);
24     }
25 
26     @Override
27     public void subscribe(ISubject subject) {
28         if (subject != null) {
29             this.subject = subject;
30         }
31         if (this.subject != null) {
32             this.subject.attach(this);
33         }
34     }
35 
36     @Override
37     public void unsubscribe() {
38         if (this.subject != null) {
39             this.subject.detach(this);
40         }
41     }
42 
43     @Override
44     public void update(ISubject subject) {
45         if (subject == this.subject) {
46             // 自己的业务
47         }
48     }
49 
50     @Override
51     protected void finalize() throws Throwable {
52         unsubscribe();
53         this.subject = null;
54         super.finalize();
55     }
56 }

上述是基类/父类,后续再继承各自的父类,进行实际业务的开展。

【实际业务的代码以及测试,这里不写了】

 
 
特别说明:
在不考虑效率的情况下,上述代码可以了。
但更多的时候,更多业务和资源,不允许不限制使用。
 
说简单点,在上述的情况下,需要做一个资源优化(比如,重复刷新、频繁刷新、占用资源过多如何处理、推或拉的效率问题)。这个取决于业务本身。
再比如:
1、需要观察多个目标,是观察者模式1对多关系的升级扩展
2、更新协议-推拉模型的选定或混用
3、封装复杂的更新语义

posted @ 2020-09-09 11:39  西就东城  阅读(233)  评论(0编辑  收藏  举报