• 设计模式之观察者模式


    观察者模式

    概述

    观察者模式(有时又被称为模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

    在观察者模式中,当观察对象的状态发生变化时,会通知给观察者,观察者模式适用于根据对象状态进行相应处理的场景。

    示例程序

    在示例程序中,观察者将贯穿一个会生成数值的对象,并且将它生成的数值结果显示出来。不过每个观察者显示的方式不一样,DigitObserver会以数字形式显示数值,GraphIbserver会以简单的图形显示数值。

    名称说明
    Observer观察者的接口
    NumberGenerator生成数值的对象的抽象类
    RandomNumberGenerator随机生成数值的类
    DigitObserver以数字形式显示数值的类
    GraphIbserver以图形形式显示数值的类

    代码实现

    Observer

    Observer是表示观察者的接口,具体的观察者会实现该接口,NumberGenerator类会调用update方法,如果调用了update方法,NumberGenerator类就会将变化的数值发送给Observer

    public interface Observer {
        void update(NumberGenerator numberGenerator);
    }
    
    • 1
    • 2
    • 3

    NumberGenerator

    NumberGenerator是生成数值的抽象类,他可以保存多个观察者,包括有注册、删除、给所有观察者发送信息的方法。而获取数值、生成数值由他的子类实现

    public abstract class NumberGenerator {
        //保存观察者
        private List<Observer> observers = new ArrayList<>();
    
        //注册观察者
        public void addObserver(Observer observer){
            observers.add(observer);
        }
    
        //删除观察者
        public void deleteObserver(Observer observer){
            observers.remove(observer);
        }
    
        //向观察者们发送信息
        public void sendObservers(){
            Iterator<Observer> iterator = observers.iterator();
            while (iterator.hasNext()){
                iterator.next().update(this);
            }
        }
    
        //获取数值
        public abstract int getNumber();
        //生成数值
        public abstract void execute();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    RandomNumberGenerator

    RandomNumberGenerator方法用于随机生成数值,并调用自己的sendObservers方法来像观察者发送消息

    public class RandomNumberGenerator extends NumberGenerator {
        private Random random = new Random();
    
        private int number;
    
        @Override
        public int getNumber() {
            return number;
        }
    
        @Override
        public void execute() {
            for (int i = 0; i < 20; i++) {
                number = random.nextInt(50);
                sendObservers();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    DigitObserver、GraphObserver

    具体的观察者,会记录发送过来的消息

    public class DigitObserver implements Observer {
        @Override
        public void update(NumberGenerator numberGenerator) {
            System.out.println("DigitObserver: " + numberGenerator.getNumber());
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public class GraphObserver implements Observer {
        @Override
        public void update(NumberGenerator numberGenerator) {
            System.out.print("GraphObserver: ");
            for (int i = 0; i < numberGenerator.getNumber(); i++) {
                System.out.print("*");
            }
            System.out.println();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    登场角色

    • Subject(观察对象)

      Subject表示观察对象,Subject角色定义了注册观察者和删除观察者的方法。此外它还声明了获取现在的状态的方法。在示例程序中,由NumberGenerator扮演

    • ConcreteSubject(具体的观察者)

      ConcreteSubject表示具体的被观察对象,当自身发生变化后,他会通知所有已经注册的Obeserver角色,在示例程序中由RandomNumberGenerator扮演

    • Observer(观察者)

      Observer角色负责接收Subject角色的状态变化的通知,在示例程序中由Observer扮演

    • ConcreteObserver(具体的观察者)

      ConcreteObserver角色表示具体的Observer,当他的update方法被调用时,会去获取被观察者的最新状态,在示例程序中由DigitObserver、GraphObserver扮演

    总结

    小黄感觉这个观察者并不是在执行一个大家理念中的观察者角色,更像是一个订阅者的概念,Subject角色发生变化时,主动告知Observer角色。有点类似于MQ中的Publish-Subscribe(发布订阅模式)。

    优点

    可以让类之间隔离,定义了稳定的消息更新传递机制,抽象了更新接口,让各个被统治的类具体处理自己的更新操作

    缺点

    如果一个对象有多个观察者,那么通知所有的观察者会花费很多时间

  • 相关阅读:
    java毕业设计房屋出租mybatis+源码+调试部署+系统+数据库+lw
    并列连词详解
    VMware Workstation Pro 12 ubuntu 20.04 突然奔溃,重新打开后导致win11系统蓝屏问题
    点云从入门到精通技术详解100篇-基于3D点云的曲面文字检测
    【网络基础】——HTTPS
    fetch网络请求详解
    JavaScriptJQuery_jQuery CSS样式操作
    6.1数值积分问题&6.2插值型求积公式
    PEG/蛋白Protein/抗体antibody 功能化修饰硫化锌量子点 ZnS QDs
    【Spring Security 系列】(三)剖析基础组件之授权功能
  • 原文地址:https://blog.csdn.net/Yellow_Star___/article/details/125429207