c++11设计模式 观察者模式 任意参数注册 不继承

当对象间存在一对多的依赖关系时,当一个对象被修改时,则会自动通知所有依赖于它的对象。这种情况就可以使用观察者模式。本文的观察者模式消除了传统的观察者模式中观察者和主题的需要继承的强耦合关系,可以注册任意参数的函数,灵活性更高。

#include <unordered_map>
#include <string>
#include <functional>
#include <iostream>

template<typename Callable>
class Subject {
public:
    Subject() : observer_id_{0} {}
    ~Subject() {}

    int Attach(Callable&& f) {
        return Add(f);
    }

    int Attach(const Callable& f) {
        return Add(f);
    }

    int Remove(int key) {
        return observers_.erase(key);
    }

    template<typename...Args>
    std::unordered_map<int, int> Update(Args&&...args) {
        std::unordered_map<int, int> rets;
        for (auto const& observer : observers_) {
            rets.emplace(observer.first,
                observer.second(std::forward<Args>(args)...));
        }
        return rets;
    }

private:
    template<typename F>
    int Add(F&& f) {
        int ret = observer_id_;
        observers_.emplace(ret, std::forward<F>(f));
        ++observer_id_;
        return ret;
    }

    int observer_id_;
    std::unordered_map<int, Callable> observers_;
};

class Task1 {
 public:
    int Add(const int a, const int b) {
        std::cout << "do task1" << std::endl;
        return a+b;
    }
};

class Task2 {
 public:
    int operator()(const int a, const int b) {
        std::cout << "do task2" << std::endl;
        return a*b;
    }
};

int main() {
    Subject<std::function<int(int, int)>> subject;

    Task1 task1;
    auto task1_key = subject.Attach(
        std::bind(&Task1::Add, &task1, std::placeholders::_1, std::placeholders::_2));

    Task2 task2;
    auto task2_key = subject.Attach(task2);

    auto lambda_key = subject.Attach([](int a, int b){
            std::cout << "do lambda" << std::endl;
            return a -b;});

    auto ret = subject.Update(10, 5);

    std::cout << "task1 ret:" << ret[task1_key] << std::endl;
    std::cout << "task2 ret:" << ret[task2_key] << std::endl;
    std::cout << "lambda ret:" << ret[lambda_key] << std::endl;

    subject.Remove(lambda_key);
    subject.Update(10, 5);
    return 0;
}

class内部成员observers_是一个unordered_map,用来保存观察者注册的消息,这个消息是一个泛型函数,可以通过key来找到对应的消息。这个key主要用来区分消息,实现保存消息的返回值以及移除消息。
在使用的时候,观察者只需要调用Attach将函数添加进来,同时保存key。添加的函数是可调用的类型,示例中使用了std::bind和成员函数有operator()的对象,以及lambda表达式。有更新的时候只需要调用Update即可执行所有注册的函数。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值