本文共 4189 字,大约阅读时间需要 13 分钟。
观察者模式(Observer),又叫发布-订阅(Publish/Subscribe)模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某个主题对象,这个主题对象发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
1、主题类
public abstract class Subject { private Listobservers = new ArrayList<>(); /** * 增加观察者 * @param observer */ public void attach(Observer observer){ observers.add(observer); } /** * 移除观察者 * @param observer */ public void detach(Observer observer){ observers.remove(observer); } /** * 通知 */ public void notifyObservers(){ for (Observer observer:observers) { observer.update(); } }}
2、观察者
public abstract class Observer { public abstract void update();}
3、具体主题
public class ConcreteSubject extends Subject{ private String subjectState; public String getSubjectState() { return subjectState; } public void setSubjectState(String subjectState) { this.subjectState = subjectState; }}
4、具体观察者
public class ConcreteObserver extends Observer { private String name; private String observerState; private ConcreteSubject concreteSubject; public ConcreteObserver(String name, ConcreteSubject concreteSubject) { this.name = name; this.concreteSubject = concreteSubject; } public ConcreteSubject getConcreteSubject() { return concreteSubject; } public void setConcreteSubject(ConcreteSubject concreteSubject) { this.concreteSubject = concreteSubject; } @Override public void update() { observerState = concreteSubject.getSubjectState(); System.out.println("观察者"+name+",新状态是:"+observerState); }}
5、测试类
public class Test { public static void main(String[] args) { ConcreteSubject concreteSubject = new ConcreteSubject(); concreteSubject.attach(new ConcreteObserver("aa",concreteSubject)); concreteSubject.attach(new ConcreteObserver("bb",concreteSubject)); concreteSubject.attach(new ConcreteObserver("cc",concreteSubject)); concreteSubject.setSubjectState("ABC"); concreteSubject.notifyObservers(); }}输出:观察者aa,新状态是:ABC观察者bb,新状态是:ABC观察者cc,新状态是:ABC
不难发现,上述代码存在几个严重问题:一是观察者与主题之间存在互相耦合;二是违背软件设计中的开发-封闭原则;三是违背软件设计中的依赖倒转原则,我们应该让程序都依赖抽象,而不是互相依赖。
1、主题接口
public interface Subject { /** * 增加观察者 * @param observer */ public void attach(Observer observer); /** * 移除观察者 * @param observer */ public void detach(Observer observer); /** * 通知 */ public void notifyObservers();}
2、观察者接口
public interface Observer { void update(String message);}
3、具体主题
public class ConcreteSubject implements Subject{ //注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程 private Listlist; private String message; public ConcreteSubject() { list = new ArrayList<>(); } @Override public void attach(Observer observer) { list.add(observer); } @Override public void detach(Observer observer) { list.remove(observer); } @Override public void notifyObservers() { for (Observer o:list) { o.update(message); } } public void setInfomation(String s){ this.message = s; System.out.println("服务器更新消息:"+s); //通知观察者 notifyObservers(); }}
4、具体观察者
public class ConcreteObserver implements Observer { private String name; private String message; public ConcreteObserver(String name) { this.name = name; } @Override public void update(String message) { this.message = message; System.out.println(this.name+"收到消息:"+this.message); }}
5、测试类
public class Test { public static void main(String[] args) { ConcreteSubject concreteSubject = new ConcreteSubject(); Observer observer1 = new ConcreteObserver("aa"); Observer observer2= new ConcreteObserver("bb"); Observer observer3 = new ConcreteObserver("cc"); concreteSubject.attach(observer1); concreteSubject.attach(observer2); concreteSubject.attach(observer3); concreteSubject.setInfomation("PHP是世界上最好的语言!"); }}输出:服务器更新消息:PHP是世界上最好的语言!aa收到消息:PHP是世界上最好的语言!bb收到消息:PHP是世界上最好的语言!cc收到消息:PHP是世界上最好的语言!