开始使用C++学习设计模式。下面是观察者模式的实现。两个抽象类模板Observer和Subject定义了所需的接口。定义了两个特定的实现ConcreteObserver和ConcreteSubject来测试接口(我还没有找到我喜欢的用于观察者模式的好的一般现实示例,因此决定使用ConcreteWhatever)。
在这种实现中,主体将状态变化推给观察者。
#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();
}发布于 2017-12-17 15:55:14
您没有为Observer和Subject定义虚拟析构函数。这会生成代码,例如
Subject<int>* a = new ConcreteSubject<int>(3);
//...
delete a;调用未定义的行为。
这个原则是良好的面向对象编程的基础之一,它规定每个类只应该有一个单独的责任来完成。但是,在您的例子中,ConcreteObserver和ConcreteSubject似乎都违反了这一点:除了作为观察员和主体履行职责之外,它们还将所有操作记录到std::cout,这应该是您程序的另一部分。
目前,您按值传递所有内容。但是,如果模板参数T不便宜地复制(假设有数百万个元素的std::vector ),该怎么办?在这种情况下,复制过多是在浪费时间和资源。相反,您应该始终通过const&传递(如果您需要更多关于何时通过引用传递以及何时通过值传递的建议,我建议您查看一下Cpp核心指南)。
std::endl通常不需要刷新底层输出缓冲区,除了插入新行外,std::endl还会这样做,如果需要,就会有flush()。几乎在所有情况下,'\n'都能做到。
https://codereview.stackexchange.com/questions/182968
复制相似问题