观察者模式(Observer)
定义
定义了一种一堆多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
UML类图
成员角色
抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
例子
主题抽象类
package com.csdhsm.pattemdesign.observer; import java.util.ArrayList; import java.util.List; /** * @Title: Subject.java * @Description: 主题抽象类 * @author: Han * @date: 2016年6月23日 下午8:38:21 */ public class Subject { private List<Observer> observers = new ArrayList<>(); //增加观察者 public void attach(Observer observer) { observers.add(observer); } //删除观察者 public void detach(Observer observer) { observers.remove(observer); } //通知所有观察者 public void notifyObserver() { for (Observer observer : observers) { observer.update(); } } }
具体主题通知者
package com.csdhsm.pattemdesign.observer; /** * @Title: ConcreteSubject.java * @Description: 具体主题通知者 * @author: Han * @date: 2016年6月23日 下午8:44:17 */ public class ConcreteSubject extends Subject { //绝体主题通知者对象 private String subjectState; public String getSubjectState() { return subjectState; } public void setSubjectState(String subjectState) { this.subjectState = subjectState; } }
抽象观察者
package com.csdhsm.pattemdesign.observer; /** * @Title: Observer.java * @Description: 抽象观察者 * @author: Han * @date: 2016年6月23日 下午8:39:06 */ public interface Observer { public void update(); }
具体观察者
package com.csdhsm.pattemdesign.observer; /** * @Title: ConcreteObserver.java * @Description: 具体观察者对象 * @author: Han * @date: 2016年6月23日 下午8:46:40 */ public class ConcreteObserver implements Observer { private String name; private String observerState; private ConcreteSubject subject; public ConcreteObserver(String name, ConcreteSubject subject) { this.name = name; this.subject = subject; } //更新状态 @Override public void update() { this.observerState = this.subject.getSubjectState(); System.out.println("观察者" + this.name + "的状态更新为" + this.observerState); } }
客户端
package com.csdhsm.pattemdesign.observer; public class Solution { public static void main(String[] args) { ConcreteSubject subject = new ConcreteSubject(); subject.attach(new ConcreteObserver("a", subject)); subject.attach(new ConcreteObserver("b", subject)); subject.attach(new ConcreteObserver("c", subject)); subject.setSubjectState("lalala"); subject.notifyObserver(); } }
结果
ok,成功!
总结
应用场景:
1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
优点
1、 Subject和Observer之间是松偶合的,分别可以各自独立改变。
2、 Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。