设计模式使用场景实现示例及优缺点(行为型模式——观察者模式)

阿尔法的身体内部有一个智能芯片,这个芯片能够根据环境和需求自动改变它的行为模式。当阿尔法需要完成不同任务时,它的内部状态会发生变化,进而改变它的行为,就像是它变成了另一个机器人一样。

一天,智能城的市长接到一个紧急消息:城市的能源核心出了问题,导致整个城市即将陷入黑暗。市长知道只有阿尔法才能解决这个问题,于是他立刻派人去找阿尔法。

阿尔法接到任务后,立即进入“修理模式”。在修理模式下,阿尔法的内部状态变为“工程师状态”,它的手臂变成了各种工具,眼睛变成了高精度的扫描仪。阿尔法迅速来到了能源核心,开始检测问题所在。

经过一番检查,阿尔法发现问题出在能源核心的控制系统上。它决定进入“编程模式”。在编程模式下,阿尔法的内部状态变为“程序员状态”,它的手指变成了键盘和电缆接口,能够直接连接到控制系统并进行编程。

阿尔法快速编写了一段修复程序,上传到控制系统中。随着程序的运行,能源核心渐渐恢复了正常,整个智能城重新亮起了光芒。

然而,阿尔法的任务并没有结束。智能城的一所学校发生了火灾,学生们被困在教学楼里。阿尔法接到新的任务后,立即进入“救援模式”。在救援模式下,阿尔法的内部状态变为“救援状态”,它的身体变得更加坚固,装备了各种救援工具和灭火设备。

阿尔法迅速赶到现场,使用灭火器扑灭了火焰,随后用强有力的臂膀破开被困学生们的教室门,将他们一个个安全地带了出来。

观察者模式(Observer Pattern)

状态模式(State Pattern)是一种行为设计模式,它允许一个对象在其内部状态改变时改变它的行为。这种模式通过将状态相关的行为封装在状态对象中,使得当对象的内部状态改变时,其行为也会随之改变,类似于它改变了其类。

核心组件

  • Subject(主题):主题保存了一组观察者,提供用于增加或删除观察者的接口。
  • Observer(观察者):为那些在主题状态改变时需要获得通知的对象定义一个更新接口。
  • ConcreteSubject(具体主题):存储具体观察者关心的数据,发送通知给观察者,通常包含对具体数据的增删改操作。
  • ConcreteObserver(具体观察者):实现观察者接口,以便在得到通知时更新自身。

适用场景

  1. 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面时
    • 观察者模式允许你独立地扩展或复用核心功能。
  2. 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要改变时
    • 观察者模式可以让你在不修改这些类的前提下增加新的观察者。
  3. 当一个对象必须通知其他对象,但你希望避免做成这些对象之间的紧密耦合时
    • 观察者模式提供了一种松耦合的设计解决方案。

实现实例

以新闻应用为例,其中新闻发布系统(主题)需要通知所有订阅者(观察者)新闻更新。

主题接口(Subject Interface)

定义了附加和删除观察者的方法,以及通知观察者的方法。

public interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}

具体主题(Concrete Subject)

存储状态,并在状态改变时通知观察者。

public class NewsAgency implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String news;

    public void registerObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(news);
        }
    }

    public void setNews(String news) {
        this.news = news;
        notifyObservers();
    }
}

观察者接口(Observer Interface)

定义更新接口,用于获取状态改变通知。

public interface Observer {
    void update(String news);
}

具体观察者(Concrete Observer)

实现观察者接口,根据通知更新自己。

public class NewsChannel implements Observer {
    private String news;

    @Override
    public void update(String news) {
        this.news = news;
        System.out.println("News Updated: " + news);
    }
}

客户端代码(Client Code)

演示如何使用观察者模式。

public class Client {
    public static void main(String[] args) {
        NewsAgency newsAgency = new NewsAgency();
        NewsChannel channel = new NewsChannel();

        newsAgency.registerObserver(channel);
        newsAgency.setNews("New update on AI technology!");
    }
}

优缺点

优点
  1. 支持广播通信
    • 观察者模式提供了一种订阅机制,可以实现消息的广播。
  2. 应用松耦合
    • 主题与观察者之间使用抽象耦合,可以轻松地添加新的观察者。
缺点
  1. 可能引发无序的更新
    • 如果观察者的更新方法引发循环依赖,可能导致系统行为难以预测。
  2. 当观察者和主题之间的依赖关系复杂时,可能需要额外的维护成本

类图

+----------------+         +------------------+
|   Subject      |-------->|   Observer       |
+----------------+         +------------------+
| + registerObserver()     | + update()       |
| + removeObserver()       |                  |
| + notifyObservers()      +------------------+
+----------------+         |
|                |         |
+----------------+         |
                           |
      +-------------------+--------+----------------+
      |                   |                 |                |
+---------------+ +-----------------+ +----------------+ +--------------+
|ConcreteSubject| |ConcreteObserver1| |ConcreteObserver2| | ...          |
+---------------+ +-----------------+ +----------------+ +--------------+
| + setNews()   | | + update()       | | + update()      | | + update()   |
+---------------+ +-----------------+ +----------------+ +--------------+

总结

观察者模式提供了一种优雅的方式来实现对象间的通信,特别适用于状态变化需要通知多个对象的场景。通过将主题与观察者解耦,增加了系统的灵活性和可扩展性,同时也需注意避免循环依赖和更新顺序问题。

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懒人w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值