博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式梳理——观察者模式
阅读量:4097 次
发布时间:2019-05-25

本文共 4189 字,大约阅读时间需要 13 分钟。

一、概述

       观察者模式(Observer),又叫发布-订阅(Publish/Subscribe)模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某个主题对象,这个主题对象发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 

二、UML图示

三、双向耦合编程实现

       1、主题类

public abstract class Subject {    private List
observers = 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 List
list; 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是世界上最好的语言!

 

你可能感兴趣的文章
js获取每一天24点的时间
查看>>
JAVA--定义一个包含整型数组参数的方法,用来接收成绩数组,进行成绩排序并输出前三名
查看>>
已选择过的酒品品种,第二次选择时,会提示选择重复
查看>>
angularjs上传多张图片并预览
查看>>
angularjs上传图片时预览-点击图片放大
查看>>
已选择过的酒品品种,第二次选择时,会提示选择重复---改进
查看>>
angularjs三级省市联动
查看>>
angularjs分页查询
查看>>
input type="number"数字过大时
查看>>
angularjs中的$watch
查看>>
点击旋转图片90度-jquery
查看>>
angualrjs--resolve使用
查看>>
AngularJS 无限滚动加载数据控件 ngInfiniteScroll
查看>>
用jsp实现登录,登录成功则跳转到登录成功页面,失败则跳转到失败页面
查看>>
jsp-session
查看>>
jsp--javabeans
查看>>
上传图片时预览获取图片原始的宽度和size大小
查看>>
web.xml文件的作用及基本配置
查看>>
HTML5头部信息解释
查看>>
angularjs默认选中--包括省市联动的默认选中
查看>>