设计模式
设计模式定义:
设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
设计模式的目的:
为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。
分类:
创建型模式 | 工厂模式 抽象工厂模式 单例模式 建造者模式 原型模式
| 这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活 |
结构型模式 | 适配器模式 桥接模式 组合模式 装饰器模式 外观模式 享元模式 代理模式
| 这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。 |
行为型模式 | 责任链模式 命令模式 解释器模式 迭代器模式 中介者模式 备忘录模式 观察者模式 状态模式 策略模式 模板模式 访问者模式
| 这些设计模式特别关注对象之间的通信。 |
设计模式之观察者模式
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
关键代码:在抽象类里有一个容器存放观察者们。
应用实例:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class CBase ///观察者基类
{
public:
virtual void update()
{
std::cout << "Base update!" << std::endl;
}
};
class A:public CBase ///观察者A类
{
public:
virtual void update()
{
std::cout << "A update" << std::endl;
}
};
class B:public CBase ///观察者B类
{
public:
virtual void update()
{
std::cout << "B update" << std::endl;
}
};
class CState ///被观察者
{
public:
void attach(CBase *base) ///绑定观察者
{
std::vector<CBase *>::iterator it = find(m_vec.begin() , m_vec.end(), base);
if( it == m_vec.end())
{
m_vec.push_back(base);
}
}
void detach(CBase *base) ///取绑观察者
{
std::vector<CBase *>::iterator it = find(m_vec.begin() , m_vec.end(), base);
if( it != m_vec.end())
{
m_vec.erase(it);
}
}
void notify() ///通知所以的观察者
{
std::vector<CBase *>::iterator it = m_vec.begin();
for( ;it != m_vec.end(); it++)
{
(*it)->update();
}
}
private:
std::vector<CBase *> m_vec; ///保存观察者
};
int main()
{
CState myState;
A devA;
B devB;
myState.attach(&devA);
myState.attach(&devB);
myState.notify();
}
总结:
以上实例只是简单介绍了观察者模式的基本原理,实际使用中存在以下缺点:
- 观察者A、观察者B都继承于同一基类;
- 状态变更类和观察者基类相耦合;
扩展:观察者模式和发布-订阅模式的异同
观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。
从图中可以看出,观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰。这样一方面实现了解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的。