设计模式(3):观察者模式

文章介绍了观察者模式的概念及其重要性,通过对比分析不使用观察者模式时的直接依赖问题,展示了如何通过观察者模式实现NewsPublisher和User类之间的松耦合。在具体实现中,定义了抽象的News和Observer接口,以及它们的实现类,从而实现主题与观察者的解耦,提高了代码的可扩展性和可维护性。
摘要由CSDN通过智能技术生成

一、什么是观察者模式?

观察者模式又称发布订阅(Publish-Subscribe)模式,顾名思义,这是一种一对多的关系,他可以让多个观察者对象同时监听某一个主题对象,这个主题对象在状态变化时,会通知所有观察者对象,使它们能够自动更新状态。

观察者模式包含以下主要角色:

  • Subject:主题,它维护一系列观察者,并提供添加/移除观察者的接口。
  • Observer:观察者,它定义一个更新接口,主题更改时更新自身的状态。
  • ConcreteSubject:具体主题,将有关状态存入各ConcreteObserver对象,并在自身状态改变时发出通知。
  • ConcreteObserver:具体观察者,存储一个指向ConcreteSubject的引用,接收到通知时更新自身状态。

二、如果不使用观察者模式的情况

如果存在一个这样的业务需求,假设我们要实现一个新闻订阅的系统,用户可以订阅不同的新闻分类,当有新闻发布时,用户可以收到通知。

显然最简单的做法是定义两个类,一个新闻发布类NewsPublisher,一个用户类User,当有消息发布时,直接通知用户。
具体实现如下:

// 新闻发布类
class NewsPublisher {
public:
    vector<User> users; // 保存每个用户信息
    void attach(User user){
        observers.push_back(observer); // 加入用户信息
    }
    void attach(User user){
        // 移除用户信息
    }
    void publishNews(string news) {
        // 直接通知每个用户
        for (auto user : users) {
            user1.receiveNews(news); 
        }
    }
}

// 用户类  
class User {
public:
    void receiveNews(string news) {
        //接收新闻  
    }
}

int main() {
    NewsPublisher publisher;
    User user1, user2, user3;
    publisher.attach(user1);
    publisher.attach(user2);
    publisher.attach(user3);
    publisher.publishNews("Hello World!"); 
}

上面这种方法的问题在于:
*NewsPublisher必须知道所有的User对象和它的方法,并直接调用它们的方法。这使得系统非常脆弱,一旦新增或者减少User类,都需要修改NewsPublisher类。
*UserNewsPublisher之间存在强耦合,不满足设计模式的原则。比如这时候我需要另外一种功能的新闻发布类,来实现一些其它的功能,那我是不是还要重新写一个类,再把刚刚的三个基础功能实现一遍,另外新加一个功能,这样代码会特别冗余。

三、使用观察者模式的情况

那该怎么实现UserNewsPublisher的松耦合呢,也就是使用观察者模式该怎么写呢?

我们可以把两个类都继承于一个抽象父类,父类写出基本的功能,具体实现如下:
1.定义抽象类News

class News {
public:
    virtual void attach(Observer* observer) = 0;
    virtual void detach(Observer* observer) = 0;
    virtual void notify() = 0;
};

2.定义观察者抽象类Observer

class Observer {
public:
    virtual void update() = 0;
};

3.实现具体主题ConcreteNews

class NewsPublisher : public Subject {
private:
    list<Observer*> observers;

public:
    void attach(Observer* observer) override {
        observers.push_back(observer); 
    }

    void detach(Observer* observer) override {
        // 移除观察者
    }

    void notify() override {
        // 通知所有观察者
    } 
};

4.实现具体观察者,即用户User

class User : public Observer {
public:
  void update() override {
    // 更新用户状态
  }
};

5.使用

NewsPublisher* publisher = new NewsPublisher();
User* user1 = new User();
User* user2 = new User();

publisher->attach(user1); 
publisher->attach(user2);

publisher->notify(); // 通知

该代码通过观察者模式实现NewsPublisher和User之间的松耦合,解决了直接依赖的问题:

  • NewsPublisher不再需要知道所有的User,只需要维护观察者列表,然后notify即可

  • 新增User不需要修改NewsPublisher类

  • 用户和发布者解耦,可以独立变化。

四、总结

使用观察者模式的优势在于解耦了主题和观察者之间的依赖关系,使得它们可以独立变化。主题不需要知道观察者的具体实现,而观察者也只需关注主题的状态变化而不需要直接与主题类耦合。这样,当需要增加新的观察者或更改通知逻辑时,不会对主题类产生影响。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值