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

目录

什么是观察者模式

观察者模式的实现

观察者模式角色

观察者模式类图

观察者模式举例

观察者模式代码实现

观察者模式的特点

优点

缺点

使用场景

注意事项

实际应用


什么是观察者模式

        观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

观察者模式的实现

观察者模式角色

  1. 主题角色(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。这个角色可以是接口,也可以是抽象类或者具体的类,因为很多情况下会与其他的模式混用,所以使用抽象类的情况比较多。
  2. 具体主题角色(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
  3. 观察者角色(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。
  4. 具体观察者角色(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致。

观察者模式类图

观察者模式举例

观察者模式代码实现

主题角色

package com.common.demo.pattern.observer;

import java.util.Vector;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 主题角色
 * @date 2023/08/07 10:37:05
 */
public abstract class Subject {
    private Vector obs = new Vector();

    public void addObserver(Observer obs) {
        this.obs.add(obs);
    }

    public void delObserver(Observer obs) {
        this.obs.remove(obs);
    }

    protected void notifyObserver() {
        for (Observer o : obs) {
            o.update();
        }
    }

    public abstract void doSomething();
}

具体主题角色

package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体主题角色
 * @date 2023/08/07 10:39:23
 */
public class ConcreteSubject extends Subject{

    @Override
    public void doSomething(){
        System.out.println("被观察者事件发生改变");
        this.notifyObserver();
    }
}

观察者角色

package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 观察者角色 观察者接口
 * @date 2023/08/07 10:30:26
 */
public interface Observer {
    void update();
}

具体观察者角色

package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体观察者角色 观察者角色A
 * @date 2023/08/07 10:40:54
 */
public class ConcreteObserverA implements Observer{

    @Override
    public void update() {
        System.out.println("观察者A收到信息,并进行业务处理");
    }
}
package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体观察者角色 观察者角色B
 * @date 2023/08/07 10:40:54
 */
public class ConcreteObserverB implements Observer{

    @Override
    public void update() {
        System.out.println("观察者B收到信息,并进行业务处理");
    }
}

测试类

package com.common.demo.pattern.observer;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 测试类
 * @date 2023/08/07 10:46:55
 */
public class ClientTest {

    public static void main(String[] args) {
        Subject sub = new ConcreteSubject();
        sub.addObserver(new ConcreteObserverA());
        sub.addObserver(new ConcreteObserverB());
        sub.doSomething();

    }
}

测试截图

设计模式行为型——观察者模式_第1张图片

观察者模式的特点

优点

  1. 实现了松耦合:观察者模式可以将被观察者和观察者之间的耦合度降低,使得它们可以独立地进行扩展和修改。
  2. 支持广播通信:建立一套广播通信触发机制,被观察者可以同时通知多个观察者,从而支持广播通信的需求。
  3. 符合开闭原则:新增或删除观察者不会影响到被观察者和其他观察者的代码,符合开闭原则的要求。

缺点

  1. 观察者过多可能导致性能问题:如果观察者过多或者观察者的处理逻辑复杂,会影响到系统的性能,花费较多的时间。
  2. 观察者和被观察者直接关联:在一些情况下,观察者和被观察者之间的直接关联可能会导致设计上的困扰。
  3. 观察者和观察目标循环依赖:在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 
  4. 观察者对所观察的目标对象黑盒操作:无相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景

  1. 当一个对象的改变需要通知其他对象,并且不希望将对象之间的耦合度过高时,可以考虑使用观察者模式。
  2. 当某个对象的状态改变需要引起一系列相关对象的更新时,不需要知道这些对象是谁,不需知道具体有多少对象有待改变,可以使用观察者模式。
  3. 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

注意事项

  1. 注意观察者和被观察者的关联方式:可以通过接口或抽象类定义观察者接口,使得被观察者只与接口进行交互,而不依赖于具体的观察者实现类。
  2. 避免循环依赖:观察者和被观察者之间应该避免出现循环依赖的情况,否则可能导致无限循环的通知。
  3. 如果顺序执行,某一观察者错误会导致系统卡壳,可采用异步方式进行通知。

实际应用

  1. 网络订阅服务:订阅者可以订阅感兴趣的内容,当内容更新时,订阅者会收到通知。
  2. 消息中间件:多个消息消费者可以同时监听一个消息主题,当主题发布消息时,所有消费者都会接收到通知并处理消息。
  3. GUI界面组件:GUI界面中的事件监听机制就是一种观察者模式的实现。

更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)

你可能感兴趣的:(设计模式,设计模式,观察者模式)