2010-02-08 34 views
6

Mẫu thiết kế quan sát đã được xác định trong STL (Giống như java.util.Observer và java.util.Observable trong Java)?Mẫu thiết kế quan sát trong C++

+2

Có lẽ là một ví dụ về thư viện chuẩn của ngôn ngữ khác có mô hình quan sát được xây dựng vào nó. –

+0

yes Jeremy, đúng là – Lucas

+0

Bạn có thể tăng cường chấp nhận không? Nếu không, tôi sẽ sẵn sàng đăng một triển khai không tăng cường tiêu chuẩn. –

Trả lời

6

Dưới đây là triển khai tham chiếu (từ Wikipedia).

#include <iostream> 
#include <string> 
#include <map> 
#include <boost/foreach.hpp> 

class SupervisedString; 
class IObserver{ 
public: 
    virtual void handleEvent(const SupervisedString&) = 0; 
}; 


class SupervisedString{ // Observable class 
    std::string _str; 
    std::map<IObserver* const, IObserver* const> _observers; 

    typedef std::map<IObserver* const, IObserver* const>::value_type item; 

    void _Notify(){ 
     BOOST_FOREACH(item iter, _observers){ 
      iter.second->handleEvent(*this); 
     } 
    } 

public: 
    void add(IObserver& ref){ 
     _observers.insert(item(&ref, &ref)); 
    } 

    void remove(IObserver& ref){ 
     _observers.erase(&ref); 
    } 

    const std::string& get() const{ 
     return _str; 
    } 

    void reset(std::string str){ 
     _str = str; 
     _Notify(); 
    } 
}; 


class Reflector: public IObserver{ // Prints the observed string into std::cout 
public: 
    virtual void handleEvent(const SupervisedString& ref){ 
     std::cout<<ref.get()<<std::endl; 
    } 
}; 

class Counter: public IObserver{ // Prints the length of observed string into std::cout 
    virtual void handleEvent(const SupervisedString& ref){ 
     std::cout<<"length = "<<ref.get().length()<<std::endl; 
    } 
}; 

int main(){ 

    SupervisedString str; 
    Reflector refl; 
    Counter cnt; 

    str.add(refl); 
    str.reset("Hello, World!"); 
    std::cout<<std::endl; 

    str.remove(refl); 
    str.add (cnt); 
    str.reset("World, Hello!"); 
    std::cout<<std::endl; 

    return 0; 
} 
+9

Khó để nghiêm túc thực hiện C++ sử dụng các tên hàm thành viên bất hợp pháp như _Notify. –

+3

Nó vẫn còn hợp lệ C + + mặc dù. –

+1

Rõ ràng nó cũng có các vấn đề khác. Kiểm tra trang thảo luận: http://en.wikipedia.org/wiki/Talk:Observer_pattern#Implementation_flaw_in_C.2B.2B – Manuel

6

Không, không. C++ STL nhỏ hơn nhiều so với Thư viện chuẩn của Java. Nếu bạn đang tìm kiếm một cái gì đó để mở rộng trên STL được hỗ trợ bởi hầu như tất cả mọi thứ, nó sẽ là giá trị tham gia một cái nhìn tại các thư viện Boost. Trong trường hợp này, bạn có thể muốn xem Boost.Signals cung cấp mô hình tín hiệu/khe.

18

Không, nhưng Boost.Signals2 cung cấp cho bạn một cái gì đó tương tự.

+2

+1, Boost.Signals thật tuyệt. Ngoài ra, hãy kiểm tra Signals2 nếu bạn có nhiều chuỗi. – Manuel

+1

Boost.Signals không được dùng nữa, nên sử dụng Boost.Signals2 thay thế. – shi

2

Observer design pattern không được xác định trong STL. Bạn có thể tham khảo "Gang of four" Design Patterns book hoặc tìm kiếm của Google sẽ cung cấp đủ chi tiết để triển khai. Nếu câu hỏi này không được trả lời sớm, tôi sẽ đăng một ví dụ nhanh.

+0

Hoặc bạn có thể sao chép-dán việc thực hiện Wikipedia mà ai đó đã liên kết trong câu trả lời khác – Manuel

+0

cảm ơn! Tín hiệu Boost trông thú vị.Tôi đã sử dụng Boost để tạo số ngẫu nhiên nhưng không bao giờ cho một mẫu quan sát hoặc tín hiệu khi họ gọi nó. Nhưng dù sao, tôi nghĩ rằng việc đánh giá mô hình quan sát GOF và tín hiệu tăng cường là một ý tưởng tốt ít nhất cho mục đích học tập. –

8

Theo như kiến ​​thức của tôi trong C++, STL không có triển khai cho mẫu Observer. Đã có một đề xuất cho Signal/Slot cho thư viện chuẩn trong TR2 mặc dù.

Có rất nhiều thư viện cung cấp triển khai cho thư viện Qt mẫu Observer là một trong những người tiên phong. Thư viện tăng cường có triển khai (xem Boost :: Signals & Boost :: Signals2).

Thư viện Poco C++ có triển khai gọn gàng mẫu quan sát viên (xem NotificationCenter).

libsigC++, cpp-events là một số thư viện khác cung cấp triển khai thẻ/tín hiệu.

2
#include <iostream> 
#include <string> 
#include <set> 
using namespace std; 
class Subject; 
class Observer { 
public: 
    virtual void update(Subject & subject) = 0; 
}; 
// also knows as Observable in literature 
class Subject 
{ 
    string state; 
    set<Observer*> observers; 
public: 
    void attachObserver(Observer *o) { observers.insert(o); } 
    void detachObserver(Observer *o) { observers.erase(o); } 
    void notifyObservers() 
    { 
    for (auto &o : observers) 
    { 
     o->update(*this); 
    } 
    } 
    string getState() { return state; } 
    void changeState(const string & s) 
    { 
    state = s; 
    notifyObservers(); 
    } 
}; 
class ObserverImpl : public Observer 
{ 
    string state; 
public: 
    void update(Subject & sbj) override 
    { 
    state = sbj.getState(); 
    } 
    string getState() { return state; } 
}; 
int main() 
{ 
    ObserverImpl a, b, c; 
    Subject subject; 
    subject.attachObserver(&a); 
    subject.attachObserver(&b); 
    subject.attachObserver(&c); 
    subject.changeState("Observer pattern"); 
    cout << a.getState() << endl; 
    cout << b.getState() << endl; 
    cout << c.getState() << endl; 
    return 0; 
} 

vui lòng xem thêm sơ đồ UML/dòng chảy http://www.patterns.pl/observer.html