• 【设计模式


    1、模式简介

    观察者模式的介绍:

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

      发布者(被观察者) + 订阅者(观察者) = 观察者模式

    观察者模式的优点:

    • 观察者和被观察者是抽象耦合的;
    • 观察者模式建立了一套触发机制(触发联动)。

    观察者模式的缺点:

    • 如果一个被观察者有很多直接或简介的观察者的话,将所有的观察者都通知到会花费很多时间;
    • 如果在观察者和被观察者之间有循环依赖的话,被观察者会触发它们之间的的循环调用,可能会导致系统崩溃(因此,在观察者模式中应该避免观察者和被观察者之间的循环调用)。

    观察者模式的适用场景:

    • 当需要完成“触发联动”的功能时,即当一个对象的状态发生变化时,会触发与之相关联的多个对象状态的改变;
    • 当观察者对象不需要知道主题对象(被观察者)的实现细节时。

    观察者模式的UML图:

    2、案例

      在这个案例中,我们模拟报社的职能:

    • 报社的业务就是出版报纸;
    • 向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,就会一直收到新报纸;
    • 当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来;
    • 只要报社还在运营,就会一直有人向他们订阅或取消订阅报纸。

    2.1、手写观察者模式

      手写的观察者模式的代码如下:

      被观察者的抽象父类Subject代码如下:

    public abstract class Subject {
        protected String name;
        protected Object thing;
    
        abstract void addObserver(Observer observer);
    
        abstract void removeObserver(Observer observer);
    
        abstract void notifyObservers();
    
        public void setThing(Object thing) {
            this.thing = thing;
            System.out.println(this.name + "发布了一条消息:" + thing.toString());
            notifyObservers();
        }
    }

      被观察者的具体类:报社类NewsOffice中的代码:

    import java.util.ArrayList;
    import java.util.List;
    
    public class NewsOffice extends Subject {
        private List<Observer> observers;
    
        public NewsOffice() {
            super.name = "报社";
            this.observers = new ArrayList<Observer>();
        }
    
        @Override
        public void addObserver(Observer observer) {
            this.observers.add(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            int index = this.observers.indexOf(observer);
            if (index >= 0) {
                this.observers.remove(observer);
            }
        }
    
        @Override
        void notifyObservers() {
            if (this.observers.size() > 0) {
                for (Observer observer : this.observers) {
                    observer.update(super.thing);
                    observer.display();
                }
            }
        }
    }

      观察者的抽象父类Observer中的代码:

    public abstract class Observer {
        protected String name;
        protected Object thing;
    
        public void update(Object thing) {
            this.thing = thing;
            System.out.println(this.name + "收到了消息:" + thing.toString());
        }
    
        public abstract void display();
    }

      具体的观察者Person1中的代码:

    public class Person1 extends Observer {
    
        public Person1() {
            super.name = "Person1";
        }
    
        @Override
        public void display() {
            System.out.println(super.name + "一边听歌一边看报纸");
        }
    }

      具体的观察者还有Person2和Company1,这里以Person1为例,有需要的朋友可以通过博客最后的GitHub地址去GitHub上下载。

      测试类Test中的代码:

    public class Test {
        public static void main(String[] args) {
            // 创建主题(被观察者)
            Subject office = new NewsOffice();
            // 创建观察者
            Observer person1 = new Person1();
            Observer person2 = new Person2();
            Observer company1 = new Compony1();
            // 为观察者注册主题
            office.addObserver(person1);
            office.addObserver(person2);
            office.addObserver(company1);
    
            // 主题发送消息
            office.setThing("第一条新闻");
            System.out.println();
            office.setThing("哈哈哈哈哈哈哈哈哈哈");
        }
    }

      运行结果如下图所示:

    2.2、JAVA内置观察者模式

      JAVA内置的观察者模式的代码如下:

      被观察者报社类NewsOffice(继承了JAVA内置的被观察者Observable类)的代码如下:

    public class NewsOffice extends Observable {
    
        public void setNews(String news) {
            System.out.println("报社发布了新闻:" + news);
            super.setChanged();
            super.notifyObservers(news);
        }
    }

      自定义的观察者CustomObserver(实现了JAVA内置的观察者接口Observer和自定义的展示接口IDisplay)的代码如下:

    // 自定义的展示接口IDisplay中的代码:
    public interface IDisplay {
        void display();
    }
    
    
    // 自定义的观察者CustomObserver中的代码:
    public abstract class CustomObserver implements Observer, IDisplay {
        protected String name;
    
        @Override
        public void update(Observable subject, Object thing) {
            System.out.println(this.name + "收到了消息:" + thing.toString());
        }
    }

      具体观察者Person1中的代码:

    public class Person1 extends CustomObserver {
    
        public Person1() {
            super.name = "Person1";
        }
    
        @Override
        public void display() {
            System.out.println(super.name + "一边听歌一边看报纸");
        }
    }

      Person2和Company1中的代码同样在GitHub中。

      测试类Test中的代码:

    public class Test {
        public static void main(String[] args) {
            // 创建主题(被观察者)
            NewsOffice office = new NewsOffice();
            // 创建三个观察者
            CustomObserver person1 = new Person1();
            CustomObserver person2 = new Person2();
            CustomObserver company1 = new Company1();
            // 为观察者注册主题
            office.addObserver(person1);
            office.addObserver(person2);
            office.addObserver(company1);
    
            // 被观察者发布消息
            office.setNews("哈哈哈哈哈哈");
            System.out.println();
            office.setNews("这不是一条垃圾新闻");
        }
    }

      运行结果如下图所示:



      最后贴出观察者模式的GitHub代码地址:【GitHub - Observer】

  • 相关阅读:
    hello world
    first demo
    Mac出现Operation not permitted
    java 获取一个数字中,各个数字出现的次数
    java 判断回文数字
    202001031
    20200103
    华为手机的系列
    java 反向打印一个数字
    java 生成两个数之间的素数
  • 原文地址:https://www.cnblogs.com/itgungnir/p/6211201.html
Copyright © 2020-2023  润新知