设计模式--观察者模式Demo

Observer Pattern

参考:https://www.cnblogs.com/adamjwh/p/10913660.html 学习

1、什么是观察者模式?(Observer Pattern)

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

1.2、对于观察者模式而言,肯定有观察者和被观察者之分。比如在一个目录下建立一个文件,这时系统会通知目录管理器增加目录,并通知磁盘减少空间,在这里,文件就是观察者,目录管理器和磁盘就是被观察者。

1.3、观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新.

1.4、UML图

2、简单实现

2.1、创建Subject

public class Subject {

    // 订阅者集合
    private List<Observer> observerlist = new ArrayList<>();

    // subject 状态
    private int state;


    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        noticeObserver();
    }

    // 添加订阅者
    public void addObserver(Observer observer){
        observerlist.add(observer);
    }

    // 通知订阅者
    public void noticeObserver(){
        for (Observer observer : observerlist) {
            observer.update();
        }
    }
}

2.2、Observer

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

2.3、实体观察类

public class FirstObserver extends Observer {

    public FirstObserver(Subject subject){
        this.subject = subject;
        this.subject.addObserver(this);
    }
    @Override
    public void update() {
        System.err.println( "FirstObserver String: "
                + Integer.toBinaryString( subject.getState() ) );
    }
}
public class SecondObserver extends Observer {

    public SecondObserver(Subject subject){
        this.subject = subject;
        this.subject.addObserver(this);
    }

    @Override
    public void update() {
        System.err.println( "SecondObserver String: "
                + Integer.toOctalString( subject.getState() ) );
    }
}

2.4发布通知

public class ObserverPatternDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();

        new FirstObserver(subject);
        new SecondObserver(subject);
        new ThirdObserver(subject);

        System.out.println(" update subject state one");
        subject.setState(0);
        System.out.println(" update subject state two");
        subject.setState(1);
        
    }
}

2.5 输出

3、深入观察者

3.1、能解决什么问题?

  • 一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
  • 一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

3.2、使用场景

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

3.3、注意事项

  • JAVA 中已经有了对观察者模式的支持类。
  • 避免循环引用。
  • 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

4、示例代码

4.1、应用场景

  • 上学时老师去开会,同学们都在教师里happy,这是我们通常会派一个人去监测老师是否回来,如果回来,他通知我们,我们速速安静学习,当然有时候没有通知到,没通知到的同学被老师抓住一顿臭骂
  • 分析:在上述场景中:订阅的事件时老师受否回来;在教室里玩的我们是订阅者,监视的同学是发布事件者(通知老师是否回来了),同时,老师也是发布事件者。

4.2、代码实现

  • 事件抽象类

    public interface Subject {
    
        /**
         * add 一个事件的订阅者
         * @param observer
         */
        void add(Observer observer);
    
        /**
         * remove一个事件的订阅者
         * @param observer
         */
        void remove(Observer observer);
    
        /**
         * 通知所有订阅者
         */
        void notice();
    
        /**
         * 状态
         * @param stateActionn
         */
        void setState(String stateActionn);
    
        String state();
    }
    
  • 订阅者抽象类

    public abstract class Observer {
    
        protected String name;
    
        /**
         * 订阅者订阅的事件
         */
        protected Subject subject;
    
        public Observer(String name, Subject subject) {
            this.name = name;
            this.subject = subject;
        }
    
        /**
         * 接收订阅事件的方法
         */
        protected abstract void update();
    }
    
    
  • 具体的事件类

    public class SpecificSubject implements Subject {
    
        /**Subject
         * 存放订阅者的集合
         */
        private List<Observer> list = new LinkedList<Observer>();
    
        private String statename;
    
    
        /**
         * add 一个事件的订阅者
         *
         * @param observer
         */
        @Override
        public void add(Observer observer) {
            list.add(observer);
        }
    
        /**
         * remove一个事件的订阅者
         *
         * @param observer
         */
        @Override
        public void remove(Observer observer) {
            list.remove(observer);
        }
    
        /**
         * 通知所有订阅者
         */
        @Override
        public void notice() {
            for (Observer observer : list) {
                observer.update();
            }
        }
    
        /**
         * 状态
         *
         * @param stateActionn
         */
        @Override
        public void setState(String stateActionn) {
            this.statename = stateActionn;
        }
    
        @Override
        public String state() {
            return statename;
        }
    }
    
  • 具体的订阅者1

    public class ObserverOne extends Observer {
    
    
        public ObserverOne(String name, Subject subject) {
            super(name, subject);
        }
    
        /**
         * 接收订阅事件的方法
         */
        @Override
        protected void update() {
            System.out.println(name+","+subject.state()+",别玩了");
        }
    }
    
  • 具体的订阅者2

    public class ObserverTwo extends Observer{
        public ObserverTwo(String name, Subject subject) {
            super(name, subject);
        }
    
        /**
         * 接收订阅事件的方法
         */
        @Override
        protected void update() {
            System.out.println(name+","+subject.state()+",别看漫画了");
        }
    }
    
    
  • 具体的订阅者3

    public class ObserverThree extends Observer{
        public ObserverThree(String name, Subject subject) {
            super(name, subject);
        }
    
        /**
         * 接收订阅事件的方法
         */
        @Override
        protected void update() {
            System.out.println(name+","+subject.state()+"别玩手机了!");
        }
    }
    
    
  • 监视同学发布老师回来的消息

    public class ClientStudent {
        public static void main(String[] args) {
            SpecificSubject subject = new SpecificSubject();
            ObserverOne one = new ObserverOne("张三", subject);
            ObserverTwo two = new ObserverTwo("李四", subject);
            ObserverThree three = new ObserverThree("王五", subject);
            subject.add(one);
            subject.add(two);
            subject.add(three);
            //  李四没通知到
            subject.remove(two);
    
            subject.setState("老师回来了");
            subject.notice();
    
        }
    }
    
  • 输出:

  • 老师发布他回来的消息

    public class ClientTeacher {
    
        public static void main(String[] args) {
            SpecificSubject subject = new SpecificSubject();
            ObserverOne one = new ObserverOne("张三", subject);
            ObserverTwo two = new ObserverTwo("李四", subject);
            ObserverThree three = new ObserverThree("王五", subject);
            subject.add(one);
            subject.add(two);
            subject.add(three);
    
    
            // 李四被老师抓住
            subject.remove(one);
            subject.remove(three);
    
            subject.setState("想挨打吗?");
            subject.notice();
    
        }
    }
    
  • 输出

posted @ 2021-03-10 20:12  一个努力的人QAQ  阅读(113)  评论(0编辑  收藏  举报