C++设计模式-观察者(3)
设计模式:在解决某一类问题场景时,有既定的,优秀的代码框架可以直接使用,其优势如下:
- 代码更易于维护,代码的可读性,复用性,可移植性,健壮性会更好
- 当软件原有需求有变更或者增加新的需求时,合理的设计模式的应用,能够做到软件设计要求的
开-闭原则
,即对修改关闭,对扩展开放,使软件原有功能修改,新功能扩充非常灵活
- 合理的设计模式的选择,会使软件设计更加模块化,积极的做到软件设计遵循的根本原则
高内聚,低耦合
软件设计开-闭原则
:
开闭原则是软件设计中的一个重要原则,指的是软件实体(如类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在不修改现有代码的基础上,通过扩展新功能来满足新的需求,从而提高软件的灵活性和可维护性
对扩展开放:允许在现有系统中添加新功能
对修改关闭:不需要修改现有的代码来添加新功能,避免引入新错误
通过遵循开闭原则,可以提高代码的可复用性和稳定性。常用的方法包括使用抽象类、接口以及多态等技术
行为型设计模式:
行为型设计模式是一类设计模式,关注对象之间的责任分配和相互协作(主要关注对象之间的通信)。它们主要用于定义类和对象之间的交互方式,帮助软件系统实现更加灵活和可扩展的结构。以下是一些常见的行为型设计模式
观察者模式(Observer Pattern)
策略模式(Strategy Pattern)
命令模式(Command Pattern)
状态模式(State Pattern)
责任链模式(Chain of Responsibility Pattern)
迭代器模式(Iterator Pattern)
一、观察者模式
观察者模式(Observer Pattern)是一种行为型设计模式,定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会收到通知并自动更新。此模式通常用于事件处理系统。又称之为观察者-监听者或者发布-订阅模式
举例:
一组数据(数据对象)
有三个对象是依赖这一组数据:曲线图(对象1)、柱状图(对象2)、圆饼图(对象3)
当这一组数据(数据对象)发生改变时,对象1、对象2、对象3应该及时收到相应通知,并且自动进行更新
主要角色:
主题(Subject):持有观察者的集合,定义添加、删除和通知观察者的方法
观察者(Observer):定义一个更新接口,用于接收主题的通知
具体主题(Concrete Subject):实现主题接口,维护状态并通知观察者
具体观察者(Concrete Observer):实现观察者接口,维护与主题的同步
1.示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
| #include <iostream> #include <unordered_map> #include <memory> #include <list> using namespace std;
class Observer{ public: virtual void handle(int msgId) = 0; virtual ~Observer() {} };
class Observer1:public Observer{ public: Observer1(){} void handle(int msgId) override { switch (msgId) { case 1: cout << "Observer1 recv 1 msg" << endl; break; case 2: cout << "Observer1 recv 2 msg" << endl; break; default: cout << "Observer1 recv unknow msg" << endl; break; } } };
class Observer2:public Observer{ public: Observer2(){} void handle(int msgId) override { switch (msgId) { case 2: cout << "Observer2 recv 2 msg" << endl; break; default: cout << "Observer2 recv unknow msg" << endl; break; } } };
class Observer3:public Observer{ public: Observer3(){} void handle(int msgId) override { switch (msgId) { case 1: cout << "Observer3 recv 1 msg" << endl; break; case 3: cout << "Observer3 recv 3 msg" << endl; break; default: cout << "Observer3 recv unknow msg" << endl; break; } } };
class Subject{ public: void addObserver(Observer *obSer,int msgId) { _subMap[msgId].push_back(obSer); }
void deleteObserver(Observer *obSer) { for(auto& [key,LIST]:_subMap) { LIST.remove(obSer); } }
void notify(int msgId) { auto it = _subMap.find(msgId); if(it != _subMap.end()) { for(Observer *observer:it->second) { observer->handle(msgId); } } }
private: unordered_map<int,list<Observer*>> _subMap; };
int main() { Subject subject; Observer *p1 = new Observer1(); Observer *p2 = new Observer2(); Observer *p3 = new Observer3();
subject.addObserver(p1,1); subject.addObserver(p1,2); subject.addObserver(p2,2); subject.addObserver(p3,1); subject.addObserver(p3,3);
int msgId = 0; for(;;) { cout << "输入消息id: "; cin >> msgId; if(msgId == -1) break; subject.notify(msgId); }
delete p1; delete p2; delete p3;
return 0; }
|
2.优缺点
优点:
解耦:观察者与主题之间是松散耦合,方便扩展和维护
动态更新:观察者可以在运行时动态添加或移除
广播通信:主题向所有注册观察者广播通知
缺点:
可能有性能开销:如果观察者较多,通知过程可能较耗时
可能引起循环依赖:不小心使用可能导致循环依赖
无序通知:观察者收到通知的顺序不一定
适用场景:
事件驱动系统:如 GUI
事件处理
模型视图分离:如MVC
架构中,视图观察模型变化
对象间的联动:一个对象的改变需要引起其他对象的变化
观察者模式通过定义对象间的一对多依赖关系,使得一个对象状态改变时,依赖的对象能够自动收到通知并更新,广泛应用于事件驱动系统和实时更新场景