You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

观察者模式是否为冗余层?求其作用、适用场景及实例说明

观察者模式:为什么它不是冗余层级?

嘿,我完全懂你现在的感受——刚接触观察者模式的时候,我也心里犯嘀咕:“这不就是多套了一层吗?直接调用方法不也能搞定?”但真等碰到复杂场景,就会发现这层“冗余”其实是解耦和扩展性的核心保障。咱们结合PHP实例来掰扯清楚~

先看不用观察者模式的“朴素写法”

假设你要做一个新闻发布系统,发布新闻时要给用户发邮件和短信通知。不用观察者的话,代码大概是这样:

class NewsPublisher {
    public function publishNews($news) {
        echo "发布新闻:{$news}\n";
        // 硬编码调用邮件通知
        $emailNotifier = new EmailNotifier();
        $emailNotifier->send($news);
        // 硬编码调用短信通知
        $smsNotifier = new SmsNotifier();
        $smsNotifier->send($news);
        // 以后要加推送通知?得改这里的代码!
    }
}

class EmailNotifier {
    public function send($news) {
        echo "发送邮件通知:{$news}\n";
    }
}

class SmsNotifier {
    public function send($news) {
        echo "发送短信通知:{$news}\n";
    }
}

这里的问题很明显:每次新增/移除通知方式,都得修改NewsPublisher的代码,违反了“对扩展开放、对修改关闭”的开闭原则。而且NewsPublisher和具体的通知类耦合死了,完全没法复用。

用观察者模式重构后的代码

这就是观察者模式发挥作用的时候了,咱们来实现标准的PHP版本:

// 观察者接口:定义所有观察者必须实现的方法
interface Observer {
    public function update($news);
}

// 主题接口:定义主题的核心行为(添加/移除观察者、通知)
interface Subject {
    public function attach(Observer $observer);
    public function detach(Observer $observer);
    public function notify($news);
}

// 具体主题:新闻发布器
class NewsPublisher implements Subject {
    private $observers = [];

    // 添加观察者
    public function attach(Observer $observer) {
        $this->observers[] = $observer;
    }

    // 移除观察者
    public function detach(Observer $observer) {
        $key = array_search($observer, $this->observers);
        if ($key !== false) {
            unset($this->observers[$key]);
        }
    }

    // 通知所有观察者
    public function notify($news) {
        foreach ($this->observers as $observer) {
            $observer->update($news);
        }
    }

    // 发布新闻的核心逻辑
    public function publishNews($news) {
        echo "发布新闻:{$news}\n";
        // 只需要通知,不用管谁来接收
        $this->notify($news);
    }
}

// 具体观察者:邮件通知
class EmailNotifier implements Observer {
    public function update($news) {
        echo "发送邮件通知:{$news}\n";
    }
}

// 具体观察者:短信通知
class SmsNotifier implements Observer {
    public function update($news) {
        echo "发送短信通知:{$news}\n";
    }
}

// 使用示例
$publisher = new NewsPublisher();
$emailNotifier = new EmailNotifier();
$smsNotifier = new SmsNotifier();

// 注册观察者
$publisher->attach($emailNotifier);
$publisher->attach($smsNotifier);

$publisher->publishNews("PHP 8.3 正式发布!");

// 后来要加推送通知?不用改NewsPublisher!直接加个观察者类就行
class PushNotifier implements Observer {
    public function update($news) {
        echo "发送推送通知:{$news}\n";
    }
}

$pushNotifier = new PushNotifier();
$publisher->attach($pushNotifier);
$publisher->publishNews("Stack Overflow 推出新功能!");

观察者模式的核心作用与重要性

  • 彻底解耦依赖:主题(NewsPublisher)完全不知道具体有哪些观察者,只需要知道它们实现了Observer接口;观察者也不用关心主题的内部逻辑,只需要接收通知。两者的耦合度降到了最低。
  • 极致的扩展性:新增任何类型的通知(比如微信通知、APP推送),只需要新增一个实现Observer的类,然后注册到主题即可,完全不用修改主题代码。
  • 动态管理观察者:可以随时添加或移除观察者,比如某个用户不想接收短信通知,只需要调用detach方法移除对应的观察者,灵活度拉满。
  • 代码结构更清晰:把“触发事件”和“处理事件”的逻辑分开,主题专注于核心业务(发布新闻),观察者专注于各自的业务(发邮件、发短信),代码职责更单一。

什么时候该用观察者模式?

如果你碰到以下场景,别犹豫,直接上观察者模式:

  • 事件驱动场景:比如GUI按钮点击后多个组件响应、后端接口调用成功后触发一系列后续操作(比如订单支付成功后扣库存、加积分、发通知)。
  • 一对多状态同步:比如股票价格更新后,K线图、价格标签、通知栏等多个组件需要同步显示最新价格。
  • 订阅-发布场景:比如博客更新后通知订阅用户、公众号推文推送粉丝、消息队列的消费逻辑(本质就是分布式的观察者模式)。
  • 日志/监控系统:一个操作需要同时记录到文件日志、数据库日志、远程监控平台。

最后说回你的疑问

你觉得它是冗余层级,大概率是因为你目前的场景比较简单(比如只有一个观察者),这时候直接调用确实能完成任务。但设计模式是为了解决未来的复杂问题——当你的系统需求变多、依赖关系变复杂时,这层“冗余”就会变成你维护代码的救命稻草。

内容的提问来源于stack exchange,提问作者user9115388

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:16:19