我正在尋找一個Python PubSub庫的C++替代品,其中我沒有連接信號插槽或左右,而是可以註冊一個特殊類型的消息,而不知道可以發送的對象它。Python的PubSub /觀察員模式的C + +?
1
A
回答
2
也許你誤解了什麼信號和插槽。使用信號和插槽,您不必知道誰發送信號。您的「客戶」類只聲明插槽,外部管理員可以將信號連接到它們。
我建議你看看Qt。這是一個驚人的跨平臺庫,不僅僅是GUI支持。它可以方便有效地實現您可以使用的信號和插槽。
這些天它也被授權使用LGPL(除了GPL和商業版),所以您可以將它用於任何目的。
重新澄清您的評論,爲什麼不引發錯誤的例外?父母可以通知GUI,或者GUI可以註冊父母發出的信號。這樣父母也不必知道GUI。
+0
Qt不是公司政策的選擇原因。但是用你的方法,我需要一個知道事件發送者和接收者的經理,但我並不總是這種知識。另見對最初問題的評論。 – Andre 2009-03-04 10:35:31
2
你可以使用boost庫嗎?如果是這樣,那麼組合函數庫和綁定庫允許您執行以下操作。如果您的編譯器支持它,您可以使用tr1功能執行相同的操作。
#include <iostream>
#include <list>
#include <boost/function.hpp>
#include <boost/bind.hpp>
typedef boost::function< void() > EVENT_T ;
template<typename F>
class Subject
{
public:
virtual void attach (F o)
{
obs_.push_back (o);
}
virtual void notify()
{
for (typename std::list<F>::iterator i = obs_.begin(); i != obs_.end(); ++i)
(*i)();
}
private:
std::list<F> obs_;
} ;
class Button : public Subject<EVENT_T>
{
public:
void onClick()
{
notify() ;
};
};
class Player
{
public:
void play()
{
std::cout << "play" << std::endl ;
}
void stop()
{
std::cout << "stop" << std::endl ;
}
};
class Display
{
public:
void started()
{
std::cout << "Started playing" << std::endl ;
}
};
Button playButton ;
Button stopButton ;
Player thePlayer;
Display theDisplay ;
int main (int argc, char **argv)
{
playButton.attach (boost::bind (&Player::play, &thePlayer));
playButton.attach (boost::bind (&Display::started, &theDisplay));
stopButton.attach (boost::bind (&Player::stop, &thePlayer));
playButton.onClick() ;
stopButton.onClick() ;
return 0;
}
所以,當你運行這個你:
play
Started playing
stop
Press any key to continue.
所以..這是那種你正在尋找的東西?
編輯:boost :: signal庫也可能做你想做的。
2
你爲什麼不實施一個?這不是一個複雜的模式(好吧,取決於你真正想要的)。無論如何,前段時間我已經實施了一個快速而骯髒的方法。它沒有優化,同步和單線程。我希望你能用它來創造你自己的。
#include <vector>
#include <iostream>
#include <algorithm>
template<typename MESSAGE> class Topic;
class Subscriber;
class TopicBase
{
friend class Subscriber;
private:
virtual void RemoveSubscriber(Subscriber* subscriber)=0;
};
template<typename MESSAGE>
class Topic : public TopicBase
{
friend class Subscriber;
private:
class Callable
{
public:
Callable(Subscriber* subscriber, void (Subscriber::*method)(const MESSAGE&))
:m_subscriber(subscriber)
,m_method(method)
{
}
void operator()(const MESSAGE& message)
{
(m_subscriber->*m_method)(message);
}
bool operator==(const Callable& other) const
{
return m_subscriber == other.m_subscriber && m_method == other.m_method;
}
public:
Subscriber* m_subscriber;
void (Subscriber::*m_method)(const MESSAGE&);
};
public:
~Topic()
{
//unregister each subscriber
for(std::vector<Callable>::iterator i = m_subscribers.begin(); i != m_subscribers.end(); i++)
{
std::vector<TopicBase*>& topics = i->m_subscriber->m_topics;
for(std::vector<TopicBase*>::iterator ti = topics.begin();;)
{
ti = std::find(ti, topics.end(), this);
if(ti == topics.end()) break;
ti = topics.erase(ti);
}
}
}
void SendMessage(const MESSAGE& message)
{
for(std::vector<Callable>::iterator i = m_subscribers.begin(); i != m_subscribers.end(); i++)
{
(*i)(message);
}
}
private:
void Subscribe(Subscriber* subscriber, void (Subscriber::*method)(const MESSAGE&))
{
m_subscribers.push_back(Callable(subscriber, method));
subscriber->m_topics.push_back(this);
}
void Unsubscribe(Subscriber* subscriber, void (Subscriber::*method)(const MESSAGE&))
{
std::vector<Callable>::iterator i = std::find(m_subscribers.begin(), m_subscribers.end(), Callable(subscriber, method));
if(i != m_subscribers.end())
{
m_subscribers.erase(i);
subscriber->m_topics.erase(std::find(subscriber->m_topics.begin(), subscriber->m_topics.end(), this)); //should always find one
}
}
virtual void RemoveSubscriber(Subscriber* subscriber)
{
for(std::vector<Callable>::iterator i = m_subscribers.begin() ; i != m_subscribers.end(); i++)
{
if(i->m_subscriber == subscriber)
{
m_subscribers.erase(i);
break;
}
}
}
private:
std::vector<Callable> m_subscribers;
};
class Subscriber
{
template<typename T> friend class Topic;
public:
~Subscriber()
{
for(std::vector<TopicBase*>::iterator i = m_topics.begin(); i !=m_topics.end(); i++)
{
(*i)->RemoveSubscriber(this);
}
}
protected:
template<typename MESSAGE, typename SUBSCRIBER>
void Subscribe(Topic<MESSAGE>& topic, void (SUBSCRIBER::*method)(const MESSAGE&))
{
topic.Subscribe(this, static_cast<void (Subscriber::*)(const MESSAGE&)>(method));
}
template<typename MESSAGE, typename SUBSCRIBER>
void Unsubscribe(Topic<MESSAGE>& topic, void (SUBSCRIBER::*method)(const MESSAGE&))
{
topic.Unsubscribe(this, static_cast<void (Subscriber::*)(const MESSAGE&)>(method));
}
private:
std::vector<TopicBase*> m_topics;
};
// Test
Topic<int> Topic1;
class TestSubscriber1 : public Subscriber
{
public:
TestSubscriber1()
{
Subscribe(Topic1, &TestSubscriber1::onTopic1);
}
private:
void onTopic1(const int& message)
{
std::cout<<"TestSubscriber1::onTopic1 "<<message<<std::endl;
}
};
class TestSubscriber2 : public Subscriber
{
public:
void Subscribe(Topic<const char*> &subscriber)
{
Subscriber::Subscribe(subscriber, &TestSubscriber2::onTopic);
}
void Unsubscribe(Topic<const char*> &subscriber)
{
Subscriber::Unsubscribe(subscriber, &TestSubscriber2::onTopic);
}
private:
void onTopic(const char* const& message)
{
std::cout<<"TestSubscriber1::onTopic1 "<<message<<std::endl;
}
};
int main()
{
Topic<const char*>* topic2 = new Topic<const char*>();
{
TestSubscriber1 testSubscriber1;
Topic1.SendMessage(42);
Topic1.SendMessage(5);
}
Topic1.SendMessage(256);
TestSubscriber2 testSubscriber2;
testSubscriber2.Subscribe(*topic2);
topic2->SendMessage("owl");
testSubscriber2.Unsubscribe(*topic2);
topic2->SendMessage("owl");
testSubscriber2.Subscribe(*topic2);
delete topic2;
return 0;
}
相關問題
- 1. 觀察員?設計模式
- 2. python觀察者模式
- 3. Python的觀察者設計模式
- 4. 觀察員設計模式問題
- 5. 簡單的觀察到/觀察員rxjs
- 6. 觀察者模式 - 觀察者創建
- 7. 觀察者模式
- 8. Rxjs觀察員
- 9. C++「雙向」觀察者模式
- 10. C#觀察者模式消息過濾
- 11. 實現C++ -to-lua觀察者模式?
- 12. 觀察員可以觀察多個可觀察物嗎?
- 13. 觀察者模式Java - 使用線程的多個觀察者
- 14. 觀察者/可觀察模式的鏈接
- 15. magento sales_order_place_after觀察員
- 16. onClick vs觀察員
- 17. 觀察者模式vs MVC
- 18. 觀察者模式過載
- 19. MVC和觀察者模式
- 20. asp.net觀察者模式
- 21. 與觀察者模式
- 22. Vue.js和觀察者模式
- 23. java mvc可觀察模式
- 24. 觀察者模式類(JAVA)
- 25. 異步觀察者模式
- 26. 觀察者模式混淆
- 27. 觀察者模式或其他模式
- 28. 觀察者模式vs電抗模式
- 29. EmberJS:重構模型觀察員
- 30. C#4個觀察員執行
我認爲你需要充實一點。這是一個進程間需求還是隻是一個進程內的對象?給我們一些你需要解決的問題的背景。你已經提到Observer,它是這類問題的明顯設計模式。 – Jackson 2009-03-03 12:53:19
我有一個GUI應用程序,數據存儲在分層次的有序類。當發生錯誤時,我想引發一個包含錯誤消息和代碼的事件。現在我想要父數據類_and_ GUI對這個事件做出反應,但是數據類應該沒有關於GUI的知識,反之亦然。 – Andre 2009-03-04 10:31:52