首页 > 其他分享 >行为型设计模式之观察者模式

行为型设计模式之观察者模式

时间:2022-09-29 10:09:27浏览次数:58  
标签:通知 void 观察者 模式 world 设计模式 ConcreteSubject public

观察者模式

观察者模式,又叫发布-订阅模式,它属于行为型模式。它是定义一种一对多的依赖关系,一个主题对象可被多个观察者对象同时监听,使得每当主题对象状态变化时,所有依赖于它的对象都会得到通知并被自动更新。

观察者模式的核心是将观察者与被观察者解耦,以类似于消息/广播发送的机制联动两者,使被观察者的变动能通知到感兴趣的观察者们,从而做出相应的响应。

image.png

应用场景

1.当一个抽象模型包含两个方面内容,其中一个方面依赖于另一个方面;

2.其他一个或多个对象的变化依赖于另一个对象的变化;

3.实现类以广播机制的功能,无需知道具体收听者,只需分发广播,系统中感兴趣的对象会自动接收该广播;

4.多层级嵌套使用,形成一种链式触发机制,使得事件具备跨域(跨越两种观察者类型)通知。

例如:某商品无货时,只需要订阅到货通知,当产品到货时, 就可以向所有顾客发送消息通知,避免顾客重复、多次访问查询是否有货。

主要角色

1.抽象主题(Subject)

指被观察的对象(Observable)。该角色是一个抽象类或接口,定义了增加、删除、通知观察者对象的方法;

2.具体主题(ConcreteSubject)

具体被观察者,当其内状态变化时,会通知已注册的观察者;

3.抽象观察者(Observer)

定义了响应通知的更新方法

4.具体观察者(ConcrereObserver)

在得到状态更新时,会自动做出响应。

image.png

优缺点

优点:

1.观察者和被观察者是松耦合(抽象耦合)的,符合依赖倒置原则;

2.分离了表示层(观察者)和数据逻辑层(被观察者),并且建立了一套触发机制,使得数据的变化可以响应到多个表示层上;

3.实现了一对多的通讯机制,支持事件注册机制,支持兴趣分发机制,当被观察者触发事件时,只有感兴趣的观察者可以接收到通知。

缺点:

1.如果观察者数量过多,则事件通知会耗时较长;

2.事件通知呈线性关系,如果其中一个观察者处理事件卡壳,会影响后续的观察者接收该事件;

3.如果观察者和被观察者之间存在循环依赖,则可能造成两者之间的循环调用,导致系统崩溃。

基本使用

创建抽象主题

public interface ISubject<E> {
    void add(IObserver<E> observer);
    
    void notify(E event);
}

创建具体主题

public class ConcreteSubject<E> implements ISubject<E> {
    private List<IObserver<E>> observers = new ArrayList<IObserver<E>>();

    public void add(IObserver<E> observer) {
        if (observer != null && !observers.contains(observer)) {
            this.observers.add(observer);
        }
    }


    public void notify(E event) {
        System.out.println("准备通知观察者,通知内容:" + event);
        for (IObserver<E> observer : this.observers) {
            observer.update(event);
        }
    }
}

创建抽象观察者

public interface IObserver<E> {
    void update(E event);
}

创建具体观察者

public class ConcreteObserver<E> implements IObserver<E> {
    public void update(E event) {
        System.out.println("具体观察者得到通知,通知内容: " + event);
    }
}

客户端执行

    public static void main(String[] args) {
        // 被观察者
        ISubject<String> observable = new ConcreteSubject<String>();
        // 观察者
        IObserver<String> observer1 = new ConcreteObserver<String>();
        IObserver<String> observer2 = new ConcreteObserver<String>();
        // 新增观察者
        observable.add(observer1);
        observable.add(observer2);
        // 通知观察者
        observable.notify("hello world");
    }

准备通知观察者,通知内容:hello world
具体观察者得到通知,通知内容: hello world
具体观察者得到通知,通知内容: hello world

JDK中的Observer

JDK提供的一种观察者的实现方式,被观察者。

创建具体主题

@Data
public class ConcreteSubject extends Observable {
    private String name = "被观察者1号";

    private static final ConcreteSubject CONCRETE_SUBJECT = new ConcreteSubject();

    public static ConcreteSubject getInstance() {
        return CONCRETE_SUBJECT;
    }

    public void pushMsg(String msg) {
        System.out.println(this.name + "发布了一条新消息:" + msg + " ,准备通知观察者");
        setChanged();
        notifyObservers(msg);
    }
}

创建具体观察者

public class ConcrereObserver implements Observer {

    private String name;

    public ConcrereObserver(String name) {
        this.name = name;
    }

    public void update(Observable o, Object arg) {
        ConcreteSubject concreteSubject = (ConcreteSubject) o;
        String msg = (String) arg;
        System.out.println(this.name + "收到了新消息:" + msg + ",准备响应: " + concreteSubject.getName());
    }
}

客户端执行

    public static void main(String[] args) {
        // 创建被观察者
        ConcreteSubject concreteSubject = ConcreteSubject.getInstance();
        // 创建观察者
        ConcrereObserver concrereObserver1 = new ConcrereObserver("观察者1号");
        ConcrereObserver concrereObserver2 = new ConcrereObserver("观察者2号");

        // 新增观察者
        concreteSubject.addObserver(concrereObserver1);
        concreteSubject.addObserver(concrereObserver2);

        // 通知观察者
        concreteSubject.pushMsg("hello world");
    }
被观察者1号发布了一条新消息:hello world ,准备通知观察者
观察者2号收到了新消息:hello world,准备响应: 被观察者1号
观察者1号收到了新消息:hello world,准备响应: 被观察者1号

Guava API实现观察者模式

添加依赖

	    <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>20.0</version>
        </dependency>

创建监听事件

public class MyEvent {

    @Subscribe
    public void observer(String msg) {
        System.out.println("收到消息:" + msg);
    }
}

客户端执行

    public static void main(String[] args) {
        EventBus eventBus = new EventBus();

        MyEvent myEvent = new MyEvent();
        eventBus.register(myEvent);
        eventBus.post("hello world");
    }
收到消息:hello world

标签:通知,void,观察者,模式,world,设计模式,ConcreteSubject,public
From: https://blog.51cto.com/chencoding/5721692

相关文章

  • 对《Head First设计模式》的更多赞誉
    ​​软件方法(下)分析和设计第8章连载[20210723更新]>>​​​​ErichGamma:我把它带到健身房-对《HeadFirst设计模式》的赞誉​​​​技术书籍也香艳-《HeadFirst设计模式》......
  • 设计模式之模板方法模式
    在我们实际开发中,如果一个方法极其复杂时,如果我们将所有的逻辑写在一个方法中,那维护起来就很困难,要替换某些步骤时都要重新写,这样代码的扩展性就很差,当遇到这种情况就要考......
  • RabbitMQ原理和架构图解(附6大工作模式)
    为什么要使用RabbitMQ?1.解耦系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦。2.异步将消息写入消息队列,非必要的业务逻辑以......
  • 初识设计模式 - 装饰器模式
    简介装饰器模式主要解决的问题是,如果使用子类继承的方式扩展一个类,随着扩展功能的增多,子类会非常膨胀,包括子类的数量或子类的方法数。装饰器模式其核心还是“用组合替代......
  • 大话设计模式--------第二章策略模式
    第二章策略模式策略模式的概念很好理解,它将对象和行为分开,将行为定义为一个行为接口和具体行为的实现,每个if判断都可以理解为一个策略。比如商场有三种客户,第一种打8折,......
  • 行为型设计模式之中介者模式
    中介者模式中介者模式又称为调解者模式或调停者模式,属于行为型模式。它用一个中介对象封装系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独......
  • 化学吸附仪在各个模式下分别有哪些用途?
    化学吸附仪可进行脉冲化学吸附、程序升温还原(TPR)、程序升温氧化(TPO)和程序升温脱附(TPD),主要用于表征催化剂的表面活性位点及数量、强度、活性、稳定性、选择性和失活,对研究工......
  • 行为型设计模式之备忘录模式
    备忘录模式备忘录模式又称为快照模式或令牌模式,属于行为型模式。它是指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可将该对象......
  • 设计模式 -- Singleton(单例模式)
    单例模式(Singleton)保证一个类仅有一个实例,并提供一个该实例的全局访问点。在软件系统中,经常有这样一个特殊的类,必须保证它们在系统中只存在一个示例,才能确保他们的逻辑......
  • 设计模式 -- Flyweight(享元模式)
    享元模式(Flyweight)运用共享技术有效地支持大量的细粒度对象在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行是代价——主......