Bootstrap

设计模式--观察者模式【行为型模式】

设计模式的分类

我们都知道有 23 种设计模式,这 23 种设计模式可分为如下三类:

  • 创建型模式(5 种):单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。
  • 结构型模式(7 种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式(11 种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

在这里插入图片描述

设计模式系列文章传送门

设计模式的 7 大原则

设计模式–单例模式【创建型模式】

设计模式–工厂方法模式【创建型模式】

设计模式–抽象工厂模式【创建型模式】

设计模式–建造者模式【创建型模式】

设计模式–原型模式【创建型模式】

设计模式–适配器模式【结构型模式】

设计模式–装饰器模式【结构型模式】

设计模式–代理模式【结构型模式】

设计模式–外观模式(门面模式)【结构型模式】

设计模式–桥接模式【结构型模式】

设计模式–组合模式【结构型模式】

设计模式–享元模式【结构型模式】

设计模式–策略模式【行为型模式】

设计模式–模板方法模式【行为型模式】

什么是观察者模式

观察者模式是一种典型的发布订阅模式,定义了对象间的一种一对多的依赖关系,只要一个对象的状态发生改变,其依赖的所有相关对象都会得到通知并做出想要,是一种行为型模式。

观察者模式的组成

  • 抽象被观察者:也叫主题,定义了一个接口,接口中提供了注册观察者、删除观察者、通知观察者方法。
  • 具体被观察着:也叫具体主题,实现了抽象被观察者接口,重写了其方法,并维护了一个观察者列表,当被观察者状态发生变化的时候,通知观察者列表中的所有观察者。
  • 抽象观察者:也叫订阅者,定义了一个接口,并在接口中定义了一个更新的方法。
  • 具体观察着:也叫具体订阅者,实现了抽象观察者接口,并实现具体的更新方法,也就是自己的业务逻辑。

抽象者模式案例演示

我们使用生活中的微信公众号信息推送来演示观察者模式,当我们订阅了某个微信公众号之后,公众号更新了内容的时候会给我们推送消息,这里公众号就是被观察者(主题),用户就是观察者(订阅者)。

Subscriber(抽象观察者)

Subscriber 抽象观察者定义了一个更新的接口,具体代码如下:

public interface Subscriber {

    //订阅者更新接口
    void  update(String message);

}

SubscriberImpl(具体观察者)

SubscriberImpl 具体观察者,实现了抽象观察者的更新接口,具体代码如下:

public class SubscriberImpl implements Subscriber {

    public String userName;

    public SubscriberImpl(String userName) {
        this.userName = userName;
    }

    @Override
    public void update(String message) {
        System.out.println(userName + "订阅的公众号更新内容为:" + message);
    }
}

OfficialAccount(抽象被观察者)

OfficialAccount 定义了新增、删除、通知观察者(订阅者)的方法,具体代码如下:

public interface OfficialAccount {

    //添加订阅者
    void addSubscriber(Subscriber subscriber);

    //删除订阅者
    void deleteSubscriber(Subscriber subscriber);

    //通知订阅者
    void notifySubscriber(String message);

}

OfficialAccountImpl(具体被观察者)

OfficialAccountImpl 实现了抽象被观察者接口,实现了新增、删除、通知观察者(订阅者)的方法,具体代码如下:

public class OfficialAccountImpl implements OfficialAccount {

    //订阅者列表
    public List<Subscriber> subscriberList = new ArrayList<>();

    @Override
    public void addSubscriber(Subscriber subscriber) {
        subscriberList.add(subscriber);
    }

    @Override
    public void deleteSubscriber(Subscriber subscriber) {
        subscriberList.remove(subscriber);
    }

    @Override
    public void notifySubscriber(String message) {
        for (Subscriber subscriber : subscriberList) {
            subscriber.update(message);
        }
    }
}

ObserverClient(客户端代码)

ObserverClient 模拟出发观察者模式,代码如下:

public class ObserverClient {

    public static void main(String[] args) {
        OfficialAccountImpl officialAccount = new OfficialAccountImpl();
        //订阅者
        SubscriberImpl subscriberOne = new SubscriberImpl("小明");
        SubscriberImpl subscriberTwo = new SubscriberImpl("小美");
        //添加订阅者
        officialAccount.addSubscriber(subscriberOne);
        officialAccount.addSubscriber(subscriberTwo);
        //通知订阅者订阅消息
        officialAccount.notifySubscriber("早间新闻~朝闻天下");
        //移出 订阅者 防止内存泄漏
        officialAccount.deleteSubscriber(subscriberOne);
        officialAccount.deleteSubscriber(subscriberTwo);
        System.out.println("使用完成要及时移出订阅者对象,防止内存泄漏");
        //移出完订阅者后 就不会出发消息订阅
        officialAccount.notifySubscriber("早间新闻~朝闻天下");
    }

执行结果如下:

小明订阅的公众号更新内容为:早间新闻~朝闻天下
小美订阅的公众号更新内容为:早间新闻~朝闻天下
使用完成要及时移出订阅者对象,防止内存泄漏

可以看到我们我们调用通知方法后,订阅者都订阅到了消息,结果符合预期。

特别注意:观察者使用完成后要及时移除掉,防止内存泄漏。

观察者模式的优缺点

优点:

  • 松耦合,订阅者和被订阅者之间只知道对方的接口,并不关注具体实现,降低了代码耦合度。
  • 代码灵活性良好,可以动态的增加减少观察者(订阅者)。
  • 扩展性良好,新增观察者(订阅者)并不需要修改被观察者代码。

缺点:

  • 使用观察者模式需要定义被观察者和观察者的类和接口,增加了系统的类。
  • 注意内存泄漏问题和循环引用问题。

观察者模式的使用场景

  • 当一个对象的状态发生变化的时候,需要通知多个对象时的场景。
  • 发布订阅的场景,发布一个主题,需要多个订阅者来订阅。

总结:本篇简单分享了观察者模式的概念和使用,并使用公众号订阅消息的方式来进行了案例演示,希望可以帮助到需要的朋友。

如有不正确的地方欢迎各位指出纠正。

;