美文网首页让前端飞
设计模式-观察者模式 发布/订阅模式

设计模式-观察者模式 发布/订阅模式

作者: 小小小8021 | 来源:发表于2019-01-15 23:31 被阅读3次

    设计模式-观察者模式 发布/订阅模式

    代码

    观察者接口

    public interface IHanFeiZi{
        // 当吃早饭时
        public void havBreakFast();
        // 进行娱乐活动时
        public void haveFun();
    }
    

    具体的被观察者

    public class HanFeiZi implements IHanFeiZi{
        `// 根据是否在吃饭,作为监控的标准
        private boolean isHavingBreakfast = false;
        // 判断是否在娱乐
        private boolean isHavingFun = false;
        // 当吃饭的时候
        public void haveBreakfast(){
            System.out.println("吃饭了");
            this.isHavingBreakfast = true;
        }
        // 当开始娱乐的时候
        public void haveFun(){
            System.out.println("开始娱乐");
            this.isHavingFun = true;
        }
        // 下方位get/set省去
    }
    

    观察者

    public interface ILiSi{
        // 发行有人有动静,进行行动
        public void update(String context);
    }
    
    public class LiSi implements ILiSi{
        // 首先他为一个观察者
        public void update(String str){
            System.out.println("观察到某人活动,进行汇报");
            this.reportToQinShiHuang(str);  // 调用汇报方法
            System.out.println("汇报完毕");
        }
        // 进行汇报、
        private void reportToQinShiHuang(String reportContext){
            System.out.println("进行汇报");
        }
    }
    

    最后定义中间

    class Spy extends Thread{
        private HanFeiZi hanFeiZi;
        private LiSi liSi;
        private String type;
        // 通过构造函数注入,显示将要监控谁
        public Spy(HanFeiZi _hanFeiZi, LiSi _liSi, String _type){
            this.hanFeiZi = _hanFeiZi;
            this.liSi = _liSi;
            this.type = _type;
        }
        @Override
        public void run(){
            while(true){
                if(this.type.equals("breakfast")){  // 监控是否吃早餐
                    // 如果在吃饭,则通知
                    if(this.hanFeiZi.isHavingBreakfast()){
                        this.liSi.update("在吃饭");
                        // 重置状态,继续监控
                        this.hanFeiZi.setHavingBreakfast(false);
                    }
                }else{  // 判断是否在娱乐
                    if(this.hanFeiZi.isHavingFun()){
                        this.liSi.update("在娱乐");
                        this.hanFeiZi.setHavingFun(false);
                    }
                }
            }
        }
    }
    

    场景类

    public class Client{
        public static void main(String[] args) throws interruptedException {
            // 定义两个人
            LiSi liSi = new LiSi();
            HanFeiZi hanFeiZi = new HanFeiZi();
            // 观察早餐
            Spy watchBreakfast = new Spy(hanFeiZi, lisi, "breakfast");
            watchBreak.start(); // 启动线程、
            // 继续查看都干什么
            Thread.sleep(1000);
            hanFeiZi.haveBreakfast();   // 开始吃饭
            // 如果娱乐
            Thread.sleep(1000);
            hanFeiZi.haveFun(); // 查看情况
        }
    }
    

    修改

    由于上面使用了一个死循环,会导致出现问题。并且由于多线程的缘故,会导致数据的污染问题,根本无法使用。
    修改如下

    public class HanFeiZi implements IHanFeiZi{
        // 声明李
        private ILiSi lisi = new LiSi();
        // 当吃饭的时候
        public void hanveBreakfast(){
            System.out.println("吃饭开始");
            this.liSi.update("吃饭了");
        }
        // 当娱乐的时候
        public void haveFun(){
            System.out.println("开始娱乐");
            this.liSi.update("在娱乐");
        }
    }
    

    最后书写场景类

    public class Client{
        public static void main(String[] args){
            // 定义出韩
            HanFeiZi hanFeiZi = new HanFeiZi();
            // 继续查看韩在干什么
            hanFeiZi.haveBreakfast();
            // 当其娱乐
            hanFeiZi.haveFun();
        }
    }
    

    继续改进

    如果这样聚合,如果有一堆人需要监控被观察者,这样不行,不能一个监控一个,如果此时要修改其他的监控内容,那么都要修改,违反开闭原则

    开闭原则 对扩展开放,对修改关闭

    那么,将被观察者的自身活动定义一个接口,被观察者定义接口,在统一的类HanFeiZi中实现该接口,对于观察者来说,定义一个观察者的接口,然后多名观察者分别实现该类
    被观察者

    public interface Observable {
        // 增加一个观察者
        public void addObserver(Observer observer);
        // 删除一个观察者
        public void deleteObserver(Observer observer);
        // 当发生动作的时候,通知观察者
        public void notifyObservers(String context);
    }
    

    上方是一个统一的观察者接口,所有的观察者都能实现这个接口。继续查看被观察者

    public class HanFeiZi implements Observalbe, IHanFeiZi{
        // 定义数组,用于保存观察者
        private ArrayList observerList = new ArrayList();
        // 增加观察者
        public void addObserver(Observer observer){
            this.observerList.add(observer);
        }
        // 删除观察者
        public void deleteObserver(Observer observer){
            this.observerList.remove(observer);
        }
        // 通知所有的观察者
        public void notifyObservers(String context){
            for(Observer observer:observerList){
                observer.update(context);
            }
        }
        // 当要吃饭了
        public void haveBreakfast(){
            System.out.println("吃饭");
            // 通知观察者
            this.notifyObservers("在吃饭");
        }
        // 开始娱乐
        public void haveFun(){
            System.out.println("开始娱乐");
            this.notifyObservers("在娱乐");
        }
    }
    
    // 书写观察者接口
    public interface Observer{
        // 发现动静,进行行动
        poublic void update(String context);
    }
    
    // 书写三个观察者,只需要实现观察者的接口即可
    public class LiSi implements Observer{
        // 首先要为观察者
        public void update(String str){
            System.out.println("开始活动了");
            // 汇报
            this.reportToQinShiHuang(str);
            System.out.println("汇报完毕");
        }
        // 汇报
        private void reportToQinShiHuang(String reportContext){
            System.out.println("进行汇报");
        }
    }
    

    同理,需要观察者直接实现接口即可。

    场景类

    public class Client{
        public static void main(String[] args){
            // 定义三个观察者
            Observer liSi = new LiSi();
            Observer wangSi = new WangSi();
            Observer liuSi = new LiuSi();
            // 定义被观察的
            HanFeiZi hanFeiZi = new HanFeiZi();
            // 当三个人观察韩的时候
            hanFeiZi.addObserver(liSi);
            hanFeiZi.addObserver(wangSi);
            hanFeiZi.addObserver(liuSi);
            // 然后查看在干什么
            hanFeiZi.haveBreakfast();
        }
    }
    

    这样就完成了观察者模式,当被观察的发生改变的时候,通知被通过构造方法注入的观察者,此观察者保存在动态数组中,然后当被观察者发生改变的时候,只需要使用循环通知保存在数组中的观察者即可。

    这里有一个接口,如果有多个观察者,可以定义一个接口,只需要实现这个即可即可,声明一个接口,然后使用不同的实例,对接口进行实例化。即可。

    订阅/发布模型

    观察者模式同时也叫发布订阅模型,即,消息驱动,消息发布着发布一个消息,然后通过容器实现对订阅者的进行发布,达到通知订阅者的目的,并且订阅者动态的保存在数组中。

    相关文章

      网友评论

        本文标题:设计模式-观察者模式 发布/订阅模式

        本文链接:https://www.haomeiwen.com/subject/gvzudqtx.html