• Design Pattern [5] —— 观察者模式 Observer / 发布订阅模式


    意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新(广播)

    主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

    优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

    缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

    2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃

    3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。


    我的Github里有源码,可以clone下来自己跑下:https://github.com/Yang2199/Design-Pattern/tree/master/src

    例子:

    发布者:

    import java.util.ArrayList;
    import java.util.List;
    
    public class Subject {
    
        private List<Observer> observers 
                = new ArrayList<Observer>();
        private int state;
    
        public int getState() {
            return state;
        }
    
        public void setState(int state) {   //改变发布的值
            this.state = state;
            System.out.println("发布 =====>> 十进制数: " + this.state);
            notifyAllObservers();
        }
    
        public void attach(Observer observer){  //新增订阅
            observers.add(observer);
        }
    
        public void detach(Observer observer){  //退订
            observers.remove(observer);
        }
    
        public void notifyAllObservers(){   //通知所有观察者
            for (Observer observer : observers) {
                observer.update();
            }
            System.out.println("========================");
        }
    }

    订阅者-抽象类:

    public abstract class Observer {
        protected Subject subject;
        public abstract void update();
        public abstract void detach();
    }

    下面写3个订阅者实现类:

    1)二进制观察者:

    public class BinaryObserver extends Observer{
    
        public BinaryObserver(Subject subject){
            this.subject = subject;
            this.subject.attach(this);  //构造的时候同时增加到观察者队列中
            System.out.println("新增订阅 => 二进制 观察者");
        }
    
        @Override
        public void update() {
            System.out.println( "二进制-观察者: "
                    + Integer.toBinaryString( subject.getState() ) );
        }
    
        @Override
        public void detach() {
            this.subject.detach(this);
            System.out.println("退订 => 二进制 观察者");
        }
    }

    2)八进制观察者:

    public class OctalObserver extends Observer{
    
        public OctalObserver(Subject subject){
            this.subject = subject;
            this.subject.attach(this);
            System.out.println("新增订阅 => 八进制 观察者");
        }
    
        @Override
        public void update() {
            System.out.println( "八进制-观察者: "
                    + Integer.toOctalString( subject.getState() ) );
        }
    
        @Override
        public void detach() {
            this.subject.detach(this);
            System.out.println("退订 => 八进制 观察者");
        }
    }

    3)十六进制观察者:

    public class OctalObserver extends Observer{
    
        public OctalObserver(Subject subject){
            this.subject = subject;
            this.subject.attach(this);
            System.out.println("新增订阅 => 八进制 观察者");
        }
    
        @Override
        public void update() {
            System.out.println( "八进制-观察者: "
                    + Integer.toOctalString( subject.getState() ) );
        }
    
        @Override
        public void detach() {
            this.subject.detach(this);
            System.out.println("退订 => 八进制 观察者");
        }
    }

    Test类:

    public class ObserverPatternDemo {
        public static void main(String[] args) {
            Subject subject = new Subject();
    
            HexaObserver hexaObserver = new HexaObserver(subject);
            BinaryObserver binaryObserver = new BinaryObserver(subject);
            subject.setState(15);//发布 广播
    
            OctalObserver octalObserver = new OctalObserver(subject);//新增 八进制观察者
            subject.setState(10);//发布 广播
    
            hexaObserver.detach();//十六进制观察者 退订
            subject.setState(7);//发布 广播
        }
    }

    结果:

    类图:

  • 相关阅读:
    如何调用ActiveX网页中的JavaScript函数
    VC++开发的ActiveX如何加入安全机制,避免IE中提示“在此页上的ActiveX控件和本页上的其他部分的交互可能不安全,你想允许这种交互吗?”
    ActiveX多线程回调JavaScript
    JavaScript脚本如何访问VC++开发的ActiveX中的方法
    ActiveX异步回调JavaScript
    com/atl套间编程中如何实现定时invoke容器中的方法
    VC++开发的ActiveX如何通过JavaScript脚本和EOS应用交互
    thread wrapper
    最新Mysql中文帮助
    如何避免重复的http请求
  • 原文地址:https://www.cnblogs.com/qyf2199/p/14611406.html
Copyright © 2020-2023  润新知