zoukankan      html  css  js  c++  java
  • 设计模式学习笔记十一:观察者模式

    设计模式学习笔记十一:观察者模式

    介绍

    观察者(observer)模式也叫发布-订阅模式,实现了观察者和被观察者的解耦操作,观察者可以根据自身需求选择关注哪些主题和取消关注哪些主题,当主题发生变化的时候会轮询通知观察者,所以主题和观察者之间是一对多的关系。

    典型应用

    • MQ
    • AWT事件监听
    • NIO多路复用
    • ……

    UML结构图:

    observer

    代码实现:

    1.主题接口

    package com.array7.observer;
    
    public interface Subject<T> {
        /**
         * 创建观察者
         * @param observer
         */
        public void add(Observer<T> observer);
    
        /**
         * 删除观察者
         * @param observer
         */
        public void remove(Observer<T> observer);
    
        /**
         * 轮询通知观察或者
         */
        public void notifyObservers();
    }

    2.具体主题实现

    package com.array7.observer;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * 具体的主题,即被观察者
     */
    public class ConcrectSubject implements Subject<String> {
        private Set<Observer<String>> observers;
    
        private String changeData;
    
        public ConcrectSubject() {
            observers = new HashSet<Observer<String>>();
        }
    
        @Override
        public void add(Observer<String> observer) {
            observers.add(observer);
        }
    
        @Override
        public void remove(Observer<String> observer) {
            observers.remove(observer);
        }
    
        @Override
        public void notifyObservers() {
            for (Observer<String> observer : observers) {
                observer.update(this.getChangeData());
            }
        }
    
        public String getChangeData() {
            return changeData;
        }
    
        /**
         * 触发update操作的方法
         */
        public void setChangeData(String changeData) {
            this.changeData = changeData;
            notifyObservers();
        }
    
    }
    

    3.观察者接口

    package com.array7.observer;
    
    /**
     * 观察者接口
     * @param <T>
     */
    public interface Observer<T> {
        /**
         * 状态更新通知
         * @param t
         */
        public void update(T t);
    
        /**
         * 主题已经存在了一个remove(..)方法,依然可以提供一个取消订阅的方法(可选)
         * 为了区分这里名称定义为了quit()
         */
        public void quit();
    }

    4.具体观察者实现

    package com.array7.observer;
    
    /**
     * 具体的观察者
     */
    public class ConcrectObserver implements Observer<String>, BizService<String> {
        private Subject<String> subject;
    
        public ConcrectObserver(Subject<String> subject) {
            subject.add(this);
            this.subject = subject;
        }
    
        @Override
        public void update(String str) {
            // logic
            dosmth(str);
        }
    
        @Override
        public void dosmth(String str) {
            System.out.println(Thread.currentThread().getName() + ":" + str);
        }
    
        @Override
        public void quit() {
            subject.remove(this);
        }
    }

    5.其他业务逻辑组合

    package com.array7.observer;
    /**
     * 强制在观察者具体实现类实现此方法
     */
    public interface BizService<T> {
        public void dosmth(T t);
    }
    

    6.Run

    package com.array7.observer;
    
    /**
     * 运行类
     */
    public class Run {
        public static void main(String[] args) {
            ConcrectSubject subject = new ConcrectSubject();
            // 初始化一个观察者
            new ConcrectObserver(subject);
            subject.setChangeData("abcd");
            subject.setChangeData("1234");
    
            ConcrectObserver tmpObserver = new ConcrectObserver(subject);
            subject.setChangeData("dcba");
            // 删除这个观察者
            subject.remove(tmpObserver);
    
            // 新加入的观察者,我们预计会输出两次4321 :]
            new ConcrectObserver(subject);
            subject.setChangeData("4321");
        }
    }
    

    TIPS

    在JDK中也提供的观察者模式的实现,但是JDK中的观察者接口是使用抽象类实现的。这就意味着如果想使用JDK中自带的实现,就不能再继承其他的基类了。而如果在基类继承,代码耦合度又会上来,因为可能不是所有的类都需要使用观察者。能用接口,尽量不用继承,也是设计原则之一:多用组合,少用继承

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    TPYBoard—MicroPython开发板免费试用!你最想抱走哪款?
    MicroPython最全资料集锦丨TPYBoard全系列教程之文档+例程源码
    MicroPython-GPRS教程之TPYBoardv702GPRS功能测试
    MicroPython-GPS教程之TPYBoardv702控制5110显示当前经纬度
    MicroPython之TPYBoard v102开发板控制OLED显示中文
    TPYBoard开发板ADC数模转换一: 初识ADC使用
    Set集合
    Collection接口和List集合
    在方法中抛出异常,使用throw关键字抛出异常
    捕捉异常和异常的使用原则
  • 原文地址:https://www.cnblogs.com/liushijie/p/4712897.html
Copyright © 2011-2022 走看看