很久之前,自己也曾看过一些设计模式的内容,最近在做一些程序代码设计的时,发现忘得差不多了,很多模式也只是有大致影响,决定重新将一些常用的模式复习一下。今天一个模式观察者模式。
观察者模式属于行为模式中的一种;观察者模式定对象一个一对多的依赖关系,让多个观察者对象同时监听同一个主题对象,主题对象在状态发生改变时,通知所有观察者对象使他们能够更新自己。
上面是观察者模式设计类图
subject:它是抽象主题的接口,对象通过此接口将自己注册为观察者,或将自己从观察中者删除
ConcreteSubject:一个实现主题接口的具体主题,除了实现注册和删除的方法外,它还有一个change方法,用来在状态改变时通知所有观察者
Observer:观察者接口,所有具体的观察者都实现此接口
ConcreteObserver:具体的观察者
package com.mtx.demo.observer; import java.util.ArrayList; import java.util.List; public abstract class Subject { // 保存注册的观察者对象 private List<Observer> list = new ArrayList<Observer>(); // 注册观察者对象 public void attach(Observer observer) { list.add(observer); System.out.println("添加新的观察者"); } // 删除观察者对象 public void detach(Observer observer) { list.remove(observer); System.out.println("删除一个观察者"); } // 通知所有注册的观察者对象 public void nodifyObservers(String newState) { for (Observer observer : list) { observer.update(newState); } } } 复制代码
一个具体主题
package com.mtx.demo.observer; public class ConcreteSubject extends Subject { private String state; public String getState() { return state; } // 状态发生改变,通知各个观察者 public void change(String newState) { state = newState; this.nodifyObservers(state); } } 复制代码
抽象的观察者
package com.mtx.demo.observer; public interface Observer { // 更新接口 public void update(String state); } 复制代码
一个具体观察者
package com.mtx.demo.observer; public class ConcreteObserver implements Observer { private String observerState; @Override public void update(String state) { observerState = state; System.out.println("观察者状态跟新了:" + observerState); } } 复制代码
客户端中,我们创建一个具体主题对象,在创建一个观察者对象,之后将观察注册到主题对象像上,这样当主题对象的状态改变时,所有的观察者对象都会收到通知,改变自己的状态。
package com.mtx.demo.observer; public class Client { public static void main(String[] args) { // 创建主题对象 ConcreteSubject subject = new ConcreteSubject(); // 创建观察者对象 Observer observer = new ConcreteObserver(); // 将观察者对象登记到主题对象上 subject.attach(observer); // 改变主题对象的状态 subject.change("有新的技术博客了"); } } 复制代码
运行代码结果如下
主题是一个具有状态的对象,而多个观察者可以使用这个主题的状态,多个观察者依赖主题对象来告诉他们这些状态何时改变,这就产生了一个主题对应多观察者的关系
主题只知道观察者实现了某一个接口(Observer接口),主题不用知道观察者具体是谁,做了哪些操作等,任何时候我们都可以添加新的观察者,那是因为主题唯一依赖的是一个观察者的Observer接口的对象列表,因此我们可以随时添加观察者,有新的主题出现时主题代码不用修改。
推模型会是观察者难以复用,因为每个观察者的updata方法的参数可能不同,数据量非常大的时候推模型不适合
另外Java语言提供的对观察者模式的支持,在java.util包中,提供了一个Observable类以及一个Observer接口
1.在观察者和被观察者之间建立一个抽象的耦合;
2.支持广播通信
1.如果一个被观察者对象有很多观察者,将所有观察者通知到会花费很多时间;
2.如果在被观察者之间有循环依赖,被观察者会触发他们之间的循环调用,导致系统崩溃;
3.观察者没有相应的方式使其知道所观察的对象时怎么发生变化的。
参考:Head First 设计模式