观察者模式

来源:互联网 发布:画图软件solidworks 编辑:程序博客网 时间:2024/05/24 07:43

观察者模式又名发布-订阅模式,定义了对象之间的一对多依赖,多个对象同时监听一个对象,当被监听对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新,被监听对象称为主题suject,监听对象称为观察者observer。

观察者模式结构如下(网上找的图):


简单来说,observer必须实现update方法,来接收suject状态变化时的通知及更新。suject维护一个observer列表,在状态变化时会逐个的调用observer的update方法来通知、更新observer,为此,suject须提供注册(添加observer到列表)、删除、通知更新三个方法。

观察者模式又分为两种模式:push和pull。push是指suject在状态变化时将所有的状态信息都发给observer,pull则是suject通知observer更新时,observer获取自己感兴趣的状态。

两种模式在实现上的区别:push模式下,observer的update方法接收的是状态信息,而pull模式下,update方法接收的是suject对象,这种情况下,suject须提供状态信息的get方法,让observer可以获取自己感兴趣的信息。

两种模式的优劣:push模式要求suject必须了解observer需要的状态,pull则是observer按需获取;push模式下observer的update方法的参数是具体的状态信息,发生变化时必须要重写update方法,pull模式则是将suject对象本身传给update,是最大的参数集合。

push模式具体实现:

  • suject超类
    package observer.push;import java.util.LinkedList;import java.util.List;/** * 推模式主题超类,能够注册、删除、数据变动时通知关注者 * @author sky * */public abstract class Subject {/** * 观察者名单 */private List<Observer> list = new LinkedList<>();/** * 注册观察者 * @param o 观察者 */public void addObserver(Observer o){list.add(o);}/** * 删除观察者 * @param o 观察者 */public void deleteObserver(Observer o){int i = list.indexOf(o);if (i>-1) {list.remove(i);}}/** * 通知观察者 */public void notifyObservers(String state){for (Observer o:list) {o.update(state);}}}
  • observer接口
    package observer.push;/** * 推模式观察者接口 * @author sky * */public interface Observer {public void update(String state);}
  • suject具体实现类
    package observer.push;public class ConcreteSubject extends Subject {/** * 状态 */public String state;/** * 状态是否改变的标志 */public boolean isChanged = false;/** * 状态改变后,通知观察者 */public void change(){if (isChanged) {this.notifyObservers(state);}}public String getState() {return state;}public void setState(String state) {this.state = state;isChanged = true;}public boolean isChanged() {return isChanged;}public void setChanged(boolean isChanged) {this.isChanged = isChanged;}}


  • observ具体实现类
    package observer.push;/** * 推模式观察者实现类 * @author sky * */public class ConcreteObserver implements Observer {public String name;public ConcreteObserver(String n){name=n;}@Overridepublic void update(String state) {System.out.println(name+" update new state:"+state);}}
  • 测试类:
    package observer.push;public class Test {/** * @param args */public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();Observer o1 = new ConcreteObserver("张山");Observer o2 = new ConcreteObserver("李四");subject.addObserver(o1);subject.addObserver(o2);System.out.println("准备:");subject.setState("上班了");subject.change();subject.setState("下班了");subject.change();}}

  • 输出:
    准备:张山 update new state:上班了李四 update new state:上班了张山 update new state:下班了李四 update new state:下班了

pull模式实现:

  • suject超类
    package observer.pull;import java.util.LinkedList;import java.util.List;/** * 拉模式主题超类,能够注册、删除、数据变动时通知关注者 * @author sky * */public abstract class Subject {/** * 观察者名单 */private List<Observer> list = new LinkedList<>();/** * 注册观察者 * @param o 观察者 */public void addObserver(Observer o){list.add(o);}/** * 删除观察者 * @param o 观察者 */public void deleteObserver(Observer o){int i = list.indexOf(o);if (i>-1) {list.remove(i);}}/** * 通知观察者 */public void notifyObservers(){for (Observer o:list) {o.update(this);}}}


  • observer接口
    package observer.pull;/** * 拉模式观察者接口 * @author sky * */public interface Observer {public void update(Subject s);}


  • suject具体实现类
    package observer.pull;public class ConcreteSubject extends Subject {/** * 状态 */public String state;/** * 状态是否改变的标志 */public boolean isChanged = false;/** * 状态改变后,通知观察者 */public void change(){if (isChanged) {this.notifyObservers();}}public String getState() {return state;}public void setState(String state) {this.state = state;isChanged = true;}public boolean isChanged() {return isChanged;}public void setChanged(boolean isChanged) {this.isChanged = isChanged;}}


  • observer具体实现类
    package observer.pull;/** * 拉模式观察者实现类 * @author sky * */public class ConcreteObserver implements Observer {public String name;public ConcreteObserver(String n){name=n;}@Overridepublic void update(Subject s) {String state = ((ConcreteSubject)s).getState();System.out.println(name+" update new state:"+state);}}


  • 测试类
    package observer.pull;public class Test {/** * @param args */public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();Observer o1 = new ConcreteObserver("张山");Observer o2 = new ConcreteObserver("李四");subject.addObserver(o1);subject.addObserver(o2);System.out.println("pull模式准备:");subject.setState("上班了");subject.change();subject.setState("下班了");subject.change();}}


  • 输出
    pull模式准备:张山 update new state:上班了李四 update new state:上班了张山 update new state:下班了李四 update new state:下班了


原创粉丝点击