摘抄《设计模式》
意图:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
别名:
依赖(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、封装复杂的更新语义