lambda 时代的观察者模式

问题描述 投票:0回答:1

观察者模式传统上需要观察者实现

update()
方法。

但是,当我们有 lambdas 时,我们也可以这样做:

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

class Subject
{
public:
   using CallbackClosure = std::funtion<void()>;
   void RegisterCallback(CallbackClosure&& cb) {
      closures_.push_back(std::move(cb));
   }

   void test() {
       for (auto const& cb : closures_) {
           cb();
       }
   }

private:
   std::vector<CallbackClosure> closures_;
};

// usage
int main()
{
   Subject s;
   // register here with a lambda instead of a pointer to the observer
   s.RegisterCallback([]{ std::cout << "Hey from main\n"; }
   s.test();

   return 0;
}

我知道我们当然可以让

RegisterCallback
成为一个ure virtual并让不同的主题来实现。那个界面,但上面的内容应该足以说明这个例子了。

这是实现“观察者模式”的现代方式吗?或者为观察者定义更新接口也有一些好处吗? lambda 可以简单地被视为匿名观察者吗?

c++ design-patterns lambda
1个回答
0
投票

#include <unordered_map> #include <functional> #include <iostream> namespace details { struct revoke_itf_t { virtual void revoke(std::size_t cookie) = 0; virtual ~revoke_itf_t() = default; }; struct subscription_t { std::size_t cookie; revoke_itf_t* subscriptions; // todo bool flag and move constructor ~subscription_t() { subscriptions->revoke(cookie); } }; } template<typename... args_t> class callbacks_t : public details::revoke_itf_t { public: [[nodiscard]] auto subscribe(std::function<void(args_t...)> callback) { m_subscription_id++; m_subscriptions.insert({m_subscription_id,callback}); return details::subscription_t{m_subscription_id,this}; } void operator()(args_t&&... args) { for(auto& [cookie,callback] : m_subscriptions) { callback(std::forward<args_t>(args)...); } } private: void revoke(std::size_t cookie) override { auto it = m_subscriptions.find(cookie); if ( it != m_subscriptions.end() ) { m_subscriptions.erase(it); } } std::size_t m_subscription_id{0ul}; std::unordered_map<std::size_t,std::function<void(args_t...)>> m_subscriptions; }; int main() { callbacks_t<int> subject; { auto subscription = subject.subscribe([](int value) { std::cout << value << "\n"; }); subject(1); subject(2); // subscription goes out of scope here } subject(3); }

© www.soinside.com 2019 - 2024. All rights reserved.