优秀的编程知识分享平台

网站首页 > 技术文章 正文

实现一个简单的信号槽--观察者模式

nanyue 2025-01-08 16:18:33 技术文章 6 ℃

信号槽:

信号槽机制最初是有QT框架引入,是一种广泛应用于事件通知的机制。信号和槽是一对通信机制,信号是一个事件的通知,槽是一个响应信号的回调函数。

观察者模式:

观察者模式是一种行为型设计模式,用于建立一种一对多的依赖关系,让多个观察者对象能够自动接收到主题对象(被观察者)的状态变化通知,并且通常能自发地更新自己的状态。

传统的观察者模式实现案例如下:可以发现是被观察者持有了多个观察者对象,当状态信息改变的时候,逐个通知观察对象,显然这样实现被观察者和观察者是聚合关系,还是比较耦合的,信号槽的方式来实现则比较松散。

#include <iostream>
#include <list>
#include <algorithm>

// 观察者基类
class Observer {
public:
    virtual ~Observer() {}
    virtual void update(int value) = 0;
};

// 具体观察者
class ConcreteObserver : public Observer {
private:
    std::string name;
public:
    ConcreteObserver(const std::string& n) : name(n) {}
    void update(int value) override {
        std::cout << "Observer " << name << " reacts to the event with value: " << value << std::endl;
    }
};

// 主题基类
class Subject {
private:
    std::list<Observer*> observers;
protected:
    void attach(Observer* o) {
        observers.push_back(o);
    }
    void detach(Observer* o) {
        observers.remove(o);
    }
    void notify() {
        for (Observer* o : observers) {
            o->update(10); // 假设更新的值为10
        }
    }
};

// 具体主题
class ConcreteSubject : public Subject {
private:
    int state;
public:
    void setState(int s) {
        state = s;
        notify();
    }
    int getState() {
        return state;
    }
};

int main() {
    ConcreteSubject subject;
    ConcreteObserver observer1("A");
    ConcreteObserver observer2("B");

    subject.attach(&observer1);
    subject.attach(&observer2);

    subject.setState(10); // 改变状态,通知观察者

    subject.detach(&observer1);
    subject.setState(20); // 再次改变状态,通知剩余的观察者

    return 0;
}

案例:

以下是一个基于信号槽实现的观察者模式案例,被观察者并不需要持有观察者对象。

这个案例是很简单的一个实现,目的也是为了理解信号槽这种歌解耦的设计思想。

在实际项目中,通常我们会做两点的升级:

--1 使用模板类和模板函数来实现信号和槽函数,提升代码的通用性

--2 信号触发有两种方式,一种是异步的,一种是同步的,我们这里明显是同步的,但实际项目中有可能任务消费是在其他的线程中执行的

#include <functional>
#include <iostream>
#include <vector>

class Slot {
public:
  explicit Slot(std::function<void()> f) : f_(f) {}
  void Call() { f_(); }

private:
  std::function<void()> f_;
};

class Signal {
public:
  void connect(Slot &slot) { slots_.emplace_back(slot); }
  void Emit() {
    for (auto &slot : slots_) {
      slot.Call();
    }
  }

private:
  std::vector<Slot> slots_;
};

class Observer {
public:
  explicit Observer(const std::string &name) : name_(name) {
    std::cout << "Observer " << this << " created" << std::endl;
  }

  void Notify() {
    std::cout << "Observer " << this << " notified" << std::endl;
  }

private:
  std::string name_;
};

class Subject {
public:
  void addObserver(Observer *observer) {
    Slot slot(std::bind(&Observer::Notify, observer));
    signal_.connect(slot);
  }

  void notifyObservers() { signal_.Emit(); }

private:
  Signal signal_;
};

int main(int argc, char const *argv[]) {
  Subject subject;

  Observer observer1("Observer 1");
  Observer observer2("Observer 2");

  subject.addObserver(&observer1);
  subject.addObserver(&observer2);

  std::cout << "Notifying observers..." << std::endl;
  subject.notifyObservers();

  return 0;
}

Tags:

最近发表
标签列表