本文整理了《C/C++ 學院》課程中的設計模式實作筆記,涵蓋 GoF 23 種經典模式的 C++ 完整代碼示例。每個模式包含核心結構、應用場景比喻、關鍵代碼片段,適合快速查閱與深入學習。
意圖:在不破壞封裝的前提下,捕獲物件內部狀態並外部化儲存,以便日後恢復(如資料庫備份、編輯器撤銷)。
Memo:儲存狀態快照。Originator:建立/恢復備忘錄。Caretaker:管理備忘錄集合。class Memo { public: string state; Memo(string s): state(s) {} };
class Originator {
string state;
public:
void setMemo(Memo* m) { state = m->state; }
Memo* createMemo() { return new Memo(state); }
void show() { cout << state << endl; }
};
class Caretaker {
vector memos;
public:
void save(Memo* m) { memos.push_back(m); }
Memo* getState(int i) { return memos[i]; }
};
意圖:定義一系列演算法,封裝每一個,使它們可互換(如購物車折扣策略:正常價、打折、滿減)。
CashSuper:抽象策略介面。CashNormal、CashRebate、CashReturn:具體策略。CashContext:根據條件選擇策略。意圖:提供一個介面,創建一系列相關或相依物件,無需指定具體類別(如資料庫存取:SQL Server vs Access 的 User/Department 物件)。
IFactory 定義 createUser()、createDepartment()。SqlFactory、AccessFactory 實作創建邏輯。意圖:定義創建物件的介面,由子類決定實例化哪個類別(如計算器:加減乘除各自的工廠)。
工廠方法將創建延遲到子類;抽象工廠創建產品族。
意圖:由一個工廠類根據參數決定創建哪個產品類(如運算元工廠:根據 '+' '-' '*' '/' 返回對應運算類)。
新增產品需修改工廠類,違反開閉原則。
意圖:為其他物件提供代理,控制對原物件的存取(如追求者透過代理送禮物給女生)。
意圖:確保類別只有一個實例,並提供全域存取點。
getInstance()。意圖:提供方法順序存取聚合物件元素,不暴露內部結構。
所有容器提供統一的 begin()/end() 迭代器介面,算法通過迭代器操作容器。
意圖:將作用於資料結構的操作分離,封裝在訪問者類中,新增操作無需修改結構類(如情人節禮物:花店老板挑花、禮品店老板挑卡)。
意圖:定義一對多依賴,主題狀態改變時自動通知所有觀察者(如公司 MM 情報郵件組)。
class Subject {
list observers;
public:
virtual void attach(Observer*) = 0;
virtual void detach(Observer*) = 0;
virtual void notify() = 0;
};
class Observer {
public:
virtual void update() = 0;
};
意圖:將複雜物件的建構與表示分離,使相同建構過程可創建不同表示(如 Person 建造者:瘦子/胖子的頭手身腳組裝)。
意圖:給定語言文法,定義表示並提供解釋器(如正則表達式、SQL 解析器)。
意圖:將請求封裝為物件,支援撤銷、佇列、日誌等(如服務員下單烤肉串)。
意圖:定義演算法骨架,將步驟延遲到子類實現(如追女生固定流程:巧遇、破冰、追求、接吻、得手)。
意圖:將抽象與實現解耦,使兩者可獨立變化(如手機品牌 M/N 與軟體 遊戲/通訊錄 組合)。
意圖:將一個類別介面轉換為客戶期望的另一介面(如外籍中鋒透過翻譯器適配 Player 介面)。
意圖:為子系統提供統一高層介面,降低耦合(如相機自動檔簡化操作)。
意圖:以共享方式支援大量細粒度物件(如手機常用語:共享句子模板,前綴加人名)。
意圖:透過複製原型創建新物件,避免建構開銷(如情話複製發送)。
意圖:將請求沿鏈傳遞,由其中一個處理(如請假審批:經理→總監→總經理)。
意圖:以中介者封裝物件互動,降低耦合(如聯合國安理會協調美國與伊拉克)。
意圖:動態為物件添加職責,比繼承更靈活(如給人穿衣服:T恤、大褲疊加)。
意圖:物件內部狀態改變時改變行為,彷彿換了類別(如工作狀態:上午/下午/晚上精神度不同)。
意圖:將物件組成樹結構表示「部分-整體」層次,客戶端統一處理單個與組合物件(如生日禮物:T恤+裙子+包包 = 一套)。
設計模式是軟體開發的經驗結晶,掌握其核心意圖與適用場景,能顯著提升代碼的可維護性、擴展性與復用性。實際專案中常組合使用多種模式,關鍵在於識別變化點並恰當封裝。