設計模式
設計模式定義:
設計模式是一套被反覆使用、多數人知曉的、經過分類的、代碼設計經驗的總結。
設計模式的目的:
爲了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性。
分類:
創建型模式 |
工廠模式 抽象工廠模式 單例模式 建造者模式 原型模式
|
這些設計模式提供了一種在創建對象的同時隱藏創建邏輯的方式,而不是使用 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都繼承於同一基類;
- 狀態變更類和觀察者基類相耦合;
擴展:觀察者模式和發佈-訂閱模式的異同
觀察者模式和發佈訂閱模式最大的區別就是發佈訂閱模式有個事件調度中心。
從圖中可以看出,觀察者模式中觀察者和目標直接進行交互,而發佈訂閱模式中統一由調度中心進行處理,訂閱者和發佈者互不干擾。這樣一方面實現瞭解耦,還有就是可以實現更細粒度的一些控制。比如發佈者發佈了很多消息,但是不想所有的訂閱者都接收到,就可以在調度中心做一些處理,類似於權限控制之類的。