首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >观测器设计模式的C++实现

观测器设计模式的C++实现
EN

Code Review用户
提问于 2017-12-17 15:05:36
回答 1查看 2K关注 0票数 5

开始使用C++学习设计模式。下面是观察者模式的实现。两个抽象类模板ObserverSubject定义了所需的接口。定义了两个特定的实现ConcreteObserverConcreteSubject来测试接口(我还没有找到我喜欢的用于观察者模式的好的一般现实示例,因此决定使用ConcreteWhatever)。

在这种实现中,主体将状态变化推给观察者。

代码语言:javascript
复制
#include <iostream>
#include <set>

// interfaces

template <typename T>
class Observer {
public:
    virtual void update(T subjectState)=0;
};

template <typename T>
class Subject {
public:
    virtual void registerObserver(Observer<T>* ptr_observer) = 0;
    virtual void unregisterObserver(Observer<T>* ptr_observer) = 0;
    virtual void notifyObservers() = 0;
};

// implementations

template <typename T>
class ConcreteObserver : public Observer<T> {
    Subject<T>* ptr_subject;
    T subjectState;
public:
    ConcreteObserver(Subject<T>* ptr_subject) : ptr_subject(ptr_subject) {
        std::cout << "Concrete observer " << this << " created to observe " << ptr_subject << std::endl;
        ptr_subject->registerObserver(this);
    }

    void update(T subjectState) {
        this->subjectState = subjectState;
        std::cout << "Observer " << this << " notified of subject " << ptr_subject << " state change to " << subjectState << std::endl;
    }

    void currentSubject(Subject<T>* ptr_subject) {
        ptr_subject->registerObserver(this);
        this->ptr_subject = ptr_subject;
    }

    ~ConcreteObserver() {
        ptr_subject->unregisterObserver(this);
    }
};

template <typename T>
class ConcreteSubject : public Subject<T> {
    std::set<Observer<T>*> observers;
    T state;
public:
    ConcreteSubject(T state) : state(state) {
        std::cout << "Concrete subject " << this << " created with state " << state << std::endl;
    }

    void registerObserver(Observer<T>* ptr_observer) {
        observers.insert(ptr_observer);
        std::cout << "Subject " << this << " registered observer " << ptr_observer << std::endl;
    }

    void unregisterObserver(Observer<T>* ptr_observer) {
        observers.erase(ptr_observer);
        std::cout << "Subject " << this << " unregistered observer " << ptr_observer << std::endl;
    }

    void notifyObservers() {
        for (std::set<Observer<T>*>::iterator iter = observers.begin(); iter != observers.end(); iter++) {
            (*iter)->update(state);
        }
    }

    void stateChanged() {
        notifyObservers();
    }

    T getState() {
        return state;
    }

    void setState(T state) {
        this->state = state;
        std::cout << "State of subject " << this << " changed to " << state << std::endl;
        stateChanged();
    }
};

int main() {
    std::cout << "Testing Subject-Observer implementation:" << std::endl;

    ConcreteSubject<int>* ptr_subject = new ConcreteSubject<int>(42);

    ConcreteObserver<int>* ptr_observer_1 = new ConcreteObserver<int>(ptr_subject);
    ConcreteObserver<int>* ptr_observer_2 = new ConcreteObserver<int>(ptr_subject);
    ConcreteObserver<int>* ptr_observer_3 = new ConcreteObserver<int>(ptr_subject);

    ptr_subject->setState(19);

    ptr_subject->unregisterObserver(ptr_observer_3);

    ptr_subject->setState(13);

    delete ptr_subject;

    getchar();
}
EN

回答 1

Code Review用户

发布于 2017-12-17 15:55:14

势虫

您没有为ObserverSubject定义虚拟析构函数。这会生成代码,例如

代码语言:javascript
复制
Subject<int>* a = new ConcreteSubject<int>(3);
//...
delete a;

调用未定义的行为。

单一责任原则

这个原则是良好的面向对象编程的基础之一,它规定每个类只应该有一个单独的责任来完成。但是,在您的例子中,ConcreteObserverConcreteSubject似乎都违反了这一点:除了作为观察员和主体履行职责之外,它们还将所有操作记录到std::cout,这应该是您程序的另一部分。

性能问题

目前,您按值传递所有内容。但是,如果模板参数T不便宜地复制(假设有数百万个元素的std::vector ),该怎么办?在这种情况下,复制过多是在浪费时间和资源。相反,您应该始终通过const&传递(如果您需要更多关于何时通过引用传递以及何时通过值传递的建议,我建议您查看一下Cpp核心指南)。

不使用std::endl

通常不需要刷新底层输出缓冲区,除了插入新行外,std::endl还会这样做,如果需要,就会有flush()。几乎在所有情况下,'\n'都能做到。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/182968

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档