前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >观察者模式(Observer)

观察者模式(Observer)

作者头像
Java高级架构
发布2018-07-20 15:45:37
4540
发布2018-07-20 15:45:37
举报
文章被收录于专栏:JAVA高级架构JAVA高级架构

1. 问题场景

当一个对象的状态放生改变的时候,如何让依赖于它的所有对象得到通知,并进行相应的处理?

2. UML图

Subject:目标对象,通常具有以下功能

  • 一个目标对象可以被多个观察者观察
  • 目标提供观察者注册和退订的维护
  • 当目标状态发生改变时,目标负责通知所有注册的、有效的观察者

Observer:定义观察者接口,提供目标通知时对应的更新方法,这个更新方法进行相应的业务逻辑处理,可以在这个方法回调目标对象,以获取目标对象的数据

ConcreteSubject:具体的目标对象,用来维护目标的状态,当目标状态发生改变时,通知所有注册有效的观察者,让观察者执行相应的处理

ConcreteObserver:观察者的具体对象,用来接收目标的通知,并进行相应的后续处理

3. 具体代码实现代码:

代码语言:java
复制
// Subject:public class Subject {
    //注意:Arraylist里面可以添加null元素
    private List<Observer> readers = new ArrayList<>();    public void attach(Observer reader){        if(reader != null){
            readers.add(reader);
        }
    }    public void detach(Observer reader){        if(reader != null){
            readers.remove(reader);
        }
    }    public void notifyAllReaders(){        if(readers.size() != 0){            //通过流的方式来访问
            //因为是从Newapaper方法里调用,所有this表示Newspaper实例
            readers.forEach(reader -> reader.update(this));
        }

    }
}//Newspaper:public class Newspaper extends  Subject{
    private String content;    public String getContent(){        return content;
    }    //维护目标的状态
    public void setContent(String content){        //内容更新之后通知所有观察者
        this.content = content;
        notifyAllReaders();
    }
}// Observer:public interface Observer {
    public void update(Subject subject);
}// Reader:public class Reader implements Observer {

    private String name;    public void setName(String name) {        this.name = name;
    }    public String getName() {        return name;
    }    @Override
    public void update(Subject subject) {
        System.out.println(name + "收到了报纸\n 报纸的内容为: " 
                                         + ((Newspaper)subject).getContent() );
    }
}//Client端public class Client {
    public static void main(String[] args) {       //创建一个报纸,作为被观察者
       NewsPaper subject = new NewsPaper();       //创建阅读者,也就是观察者
       Reader reader1 = new Reader();
       reader1.setName("张三");

       Reader reader2 = new Reader();
       reader2.setName("李四");

       Reader reader3 = new Reader();
       reader3.setName("王五");       //注册阅读者
       subject.attach(reader1);
       subject.attach(reader2);
       subject.attach(reader3);       //要出报纸啦
       subject.setContent("本期内容是观察者模式");
    }
}

4. 研磨设计模式

观察者模式的定义: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式把多个订阅者称为观察者Observer,多个观察者观察的对象的被称为目标Subject。

一个目标可以有任意多个观察者对象,一旦目标的状态发生改变时,所有注册的观察者就会得到通知,然后各个观察者会对通知作出相应的处理,执行相应的业务功能处理,并使自己的状态和目标对象的状态保持一致。

观察者模式的本质:触发联动

Swing中的观察者模式:Swing组件是被观察的目标,而每个实现监听的类就是观察者,监听器的接口就是观察者的接口,在调用addXXXListener方法的时候就相当于注册观察者。当组件被单击时,状态发生改变的时候,就会产生相应的通知,会调用注册的观察者的方法,就是我们所实现的监听器的方法。

扩展:区别对待观察者

代码语言:java
复制
/**
 * 定义水质监测的目标对象
 */public abstract class WaterQualitySubject {
    /**
     * 用来保存注册的观察者对象
     */
    protected List<WatcherObserver> observers = new ArrayList<WatcherObserver>();    /**
     * 注册观察者对象
     * @param observer 观察者对象
     */
    public void attach(WatcherObserver observer) {
        observers.add(observer);
    }    /**
     * 删除观察者对象
     * @param observer 观察者对象
     */
    public void detach(WatcherObserver observer) {
        observers.remove(observer);
    }    /**
     * 通知相应的观察者对象
     */
    public abstract void notifyWatchers();    /**
     * 获取水质污染的级别
     * @return 水质污染的级别
     */
    public abstract int getPolluteLevel();
}/**
 * 具体的水质监测对象
 */public class WaterQuality extends WaterQualitySubject{
    /**
     * 污染的级别,0表示正常,1表示轻度污染,2表示中度污染,3表示高度污染
     */
    private int polluteLevel = 0;    /**
     * 获取水质污染的级别
     * @return 水质污染的级别
     */
    public int getPolluteLevel() {        return polluteLevel;
    }    /**
     * 当监测水质情况后,设置水质污染的级别
     * @param polluteLevel 水质污染的级别
     */
    public void setPolluteLevel(int polluteLevel) {        this.polluteLevel = polluteLevel;        //通知相应的观察者
        this.notifyWatchers();
    }    /**
     * 通知相应的观察者对象
     */
    public void notifyWatchers() {        //循环所有注册的观察者
        for(WatcherObserver watcher : observers){                        //开始根据污染级别判断是否需要通知,由这里总控
                        if(this.polluteLevel >= 0){                            //通知监测员做记录
                            if("监测人员".equals(watcher.getJob())){
                                watcher.update(this);
                            }
                        }                        if(this.polluteLevel >= 1){                            //通知预警人员
                            if("预警人员".equals(watcher.getJob())){
                                watcher.update(this);
                            }
                        }                        if(this.polluteLevel >= 2){                            //通知监测部门领导
                           if("监测部门领导".equals(watcher.getJob())){
                                watcher.update(this);
                            }
                        }
        }
    }
}/**
 * 水质观察者接口定义
 */public interface WatcherObserver {
    /**
     * 被通知的方法
     * @param subject 传入被观察的目标对象
     */
    public void update(WaterQualitySubject subject);    /**
     * 设置观察人员的职务
     * @param job 观察人员的职务
     */
    public void setJob(String job);    /**
     * 获取观察人员的职务
     * @return 观察人员的职务
     */
    public String getJob();
}/**
 * 具体的观察者实现
 */public class Watcher implements WatcherObserver{
    /**
     * 职务
     */
    private String job;    public void update(WaterQualitySubject subject) {        //这里采用的是拉的方式
        System.out.println(job+"获取到通知,当前污染级别为:"+subject.getPolluteLevel());
    }    public String getJob() {        return this.job;
    }    public void setJob(String job) {        this.job = job;
    }
}public class Client {
    public static void main(String[] args) {        //创建水质主题对象
        WaterQuality subject = new WaterQuality();        //创建几个观察者
        WatcherObserver watcher1 = new Watcher();
        watcher1.setJob("监测人员");
        WatcherObserver watcher2 = new Watcher();
        watcher2.setJob("预警人员");
        WatcherObserver watcher3 = new Watcher();
        watcher3.setJob("监测部门领导");        //注册观察者
        subject.attach(watcher1);
        subject.attach(watcher2);
        subject.attach(watcher3);        //填写水质报告
        System.out.println("当水质为正常的时候------------------〉");
        subject.setPolluteLevel(0);
        System.out.println("当水质为轻度污染的时候---------------〉");
        subject.setPolluteLevel(1);
        System.out.println("当水质为中度污染的时候---------------〉");
        subject.setPolluteLevel(2);
    }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA高级架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 问题场景
  • 2. UML图
  • 3. 具体代码实现代码:
  • 4. 研磨设计模式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档