zoukankan      html  css  js  c++  java
  • 初探观察者模式

    观察者模式:定义了对象之间一对多的依赖,当一个对象改变状态时,他的所有依赖都会收到通知并自动更新。

    场景:有这样一个需求,风险监控的时候,某个用户关注了某个信息,并且希望这个信息有重大变动的时候能够往邮箱、手机、当前用户登录的网页发送这个信息。

    让我们来看看根据需求马上动手的代码:

    1、定义发送信息的类

    package pattern.observer;
    
    public class SendEmail {
        public void show(String message){
            System.out.println("您在XXX订阅的信息有更新,更新内容:" + message + "。该信息来自XXX邮箱");
        }
    }
    
    public class SendPhone {
        public void show(String message){
            System.out.println("您在XXX订阅的信息有更新,更新内容:"+message + "。该信息来自XXXX");
        }
    }
    
    public class SendWeb {
        public void show(String message){
            System.out.println("您订阅的信息有更新,更新内容:"+message);
        }
    }

    2、获取改变的信息并发送

    public void messageChange(String message){
            SendEmail sendEmail = new SendEmail();
            SendPhone sendPhone = new SendPhone();
            SendWeb sendWeb = new SendWeb();
    
            sendEmail.show(message);
            sendPhone.show(message);
            sendWeb.show(message);
        }

    我们来分析一下这样写代码的不足:首先,发送信息类里面的show()方法看起来像一个统一的接口,我们可以封装起来;其次,针对具体实现变成,这样会导致我们增加或删除一个发送通知的类时,我们必须要修改实现类。

    接下来,我们分析一下观察者模式是怎么实现对象一对多的情况的。

    首先实现主题接口和观察者接口

    package pattern.observer;
    
    public interface Subject {
        //注册观察者(就是发送信息的类)
        public void registerObserver(Observer observer);
        //删除观察者
        public void removeObserver(Observer observer);
        //通知观察者信息已经改变
        public void notifyObservers();
    }
    
    public interface Observer {
        //观察者接口,一旦信息有改变,执行更新操作
        public void update(String message);
    }

    然后信息实现主题(Object)接口

    package pattern.observer;
    
    import java.util.ArrayList;
    
    public class Message implements Subject{
        private String message;
        private ArrayList observers;
    
        public Message(){
            observers = new ArrayList();
        }
    
        //一旦信息符合要求,通知观察者更新信息
        public void messageChange(){
            if(message.equals("重大变化")){
                notifyObservers();
            }
        }
    
        //有信息进来就调用信息改变的方法
        public void setMessage(String message){
            this.message = message;
            messageChange();
        }
    
        @Override
        public void registerObserver(Observer observer) {
            observers.add(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            int i = observers.indexOf(observer);
            if(i>0){
                observers.remove(observer);
            }
        }
    
        @Override
        public void notifyObservers() {
            for(Object observer:observers){
                Observer o = (Observer)observer;
                o.update(message);
            }
        }
    }

    发送信息的类实现观察者(Observer)接口

    package pattern.observer;
    
    public class SendEmail implements Observer{
        private Subject subject;
    
        public SendEmail(Subject subject){
            this.subject = subject;
            subject.registerObserver(this);
        }
    
        public void show(String message){
            System.out.println("您在XXX订阅的信息有更新,更新内容:" + message + "。该信息来自XXX邮箱");
        }
    
        @Override
        public void update(String message) {
            show(message);
        }
    }
    
    public class SendPhone implements Observer{
        private Subject subject;
    
        public SendPhone(Subject subject){
            this.subject = subject;
            subject.registerObserver(this);
        }
    
        public void show(String message){
            System.out.println("您在XXX订阅的信息有更新,更新内容:"+message + "。该信息来自XXXX");
        }
    
        @Override
        public void update(String message) {
            show(message);
        }
    }
    
    public class SendWeb implements Observer{
        private Subject subject;
    
        public SendWeb(Subject subject){
            this.subject = subject;
            subject.registerObserver(this);
        }
    
        public void show(String message){
            System.out.println("您订阅的信息有更新,更新内容:"+message);
        }
    
        @Override
        public void update(String message) {
            show(message);
        }
    }

    最后实现控制器进行测试

    package pattern.observer;
    
    public class MessageController {
    
        public static void main(String[] args) {
            String messageStr = "重大变化";
            Message message = new Message();
            SendPhone sendPhone = new SendPhone(message);
            SendWeb sendWeb = new SendWeb(message);
            SendEmail sendEmail = new SendEmail(message);
    
            message.setMessage(messageStr);
        }
    
    }

    至此观察者模式完毕。


    其实还有个疑问,为什么要在观察者本身里面注册呢?

    public class SendEmail implements Observer{
        private Subject subject;
    
        public SendEmail(Subject subject){
            this.subject = subject;
            //为什么要在观察者保存Subject并且在初始化的时候用来注册
            subject.registerObserver(this);
        }
    
        public void show(String message){
            System.out.println("您在XXX订阅的信息有更新,更新内容:" + message + "。该信息来自XXX邮箱");
        }
    
        @Override
        public void update(String message) {
            show(message);
        }
    }

    是不是希望可以在观察者本身取消对消息的订阅?

    public class SendEmail implements Observer{
        private Subject subject;
    
        public SendEmail(Subject subject){
            this.subject = subject;
            this.subject.registerObserver(this);
        }
    
        public void show(String message){
            System.out.println("您在XXX订阅的信息有更新,更新内容:" + message + "。该信息来自XXX邮箱");
        }
    
        @Override
        public void update(String message) {
            show(message);
        }
    
        //取消订阅
        public void unsubscribe(){
            subject.removeObserver(this);
        }
    }
  • 相关阅读:
    Hadoop_HDFS文件读写代码流程解析和副本存放机制
    Hadoop_MapReduce流程
    Hadoop_YARN框架
    Spark任务流程笔记
    3D俄罗斯方块设计
    Hadoop_FileInputFormat分片
    二叉查找树的懒惰删除(lazy deletion)
    数组的三种随机排序方法
    SpringBoot @Async 异步处理业务逻辑和发短信逻辑
    json字符串转java对象
  • 原文地址:https://www.cnblogs.com/yzdtofly/p/9437511.html
Copyright © 2011-2022 走看看