C++常用的11種設(shè)計模式解釋及示例代碼詳解
c++常用的設(shè)計模式包括單例模式、工廠模式、抽象工廠模式、適配器模式、裝飾者模式、代理模式、外觀模式、橋接模式、組合模式、享元模式、觀察者模式和命令模式等。使用設(shè)計模式的好處:提高代碼的可讀性和可維護(hù)性;將常見的設(shè)計問題隔離程序的業(yè)務(wù)邏輯;重用已有的實現(xiàn);消除重復(fù)代碼;消除手動調(diào)整代碼以達(dá)到正確邏輯的所有痛苦。
工廠模式
C++工廠模式是一種模式,它是一種創(chuàng)建對象的有效方法。它允許我們使用一個類來負(fù)責(zé)創(chuàng)建實現(xiàn)特定接口的不同具體類的實例,而無需明確指定該實例的具體類。通過抽象出一個工廠類來負(fù)責(zé)每個子類的實例化,使得代碼的可維護(hù)性大大增加。這種模式也使得添加新類型的實例變得容易,只要擴(kuò)展工廠類即可。
#include<iostream> using namespace std; // A 'Product' class class Product { public: virtual void show() = 0; }; // A 'ConcreteProduct' class class ConcreteProduct : public Product { public: void show() { cout << "I am a ConcreteProduct object" << endl; } }; // A 'Creator' abstract class class Creator { public: virtual Product* createProduct() = 0; }; // A 'ConcreteCreator' class class ConcreteCreator : public Creator { public: Product* createProduct() { return new ConcreteProduct(); } }; // Client int main() { Creator* creator = new ConcreteCreator(); Product* product = creator->createProduct(); product->show(); return 0; }
單例模式
單例 Singleton 是設(shè)計模式的一種,其特點是只提供唯一一個類的實例,具有全局變量的特點,在任何位置都可以通過接口獲取到那個唯一實例。
class Singleton { private: static Singleton* instance; Singleton() { } public: static Singleton* getInstance() { if(instance == nullptr) instance = new Singleton(); return instance; } }; Singleton* Singleton::instance = nullptr;
以上只是一種通用實現(xiàn)教學(xué)版,即懶漢版(Lazy Singleton):單例實例在第一次被使用時才進(jìn)行初始化,這叫做延遲初始化,然而可能存在內(nèi)存泄漏的風(fēng)險,且這個代碼在單線程環(huán)境下是正確無誤的,但是當(dāng)拿到多線程環(huán)境下時這份代碼就會出現(xiàn)race condition。
C++11規(guī)定了local static在多線程條件下的初始化行為,要求編譯器保證了內(nèi)部靜態(tài)變量的線程安全性。在C++11標(biāo)準(zhǔn)下,《Effective C++》提出了一種更優(yōu)雅的單例模式實現(xiàn),使用函數(shù)內(nèi)的 local static 對象。這樣,只有當(dāng)?shù)谝淮卧L問getInstance()方法時才創(chuàng)建實例。這種方法也被稱為Meyers' Singleton。C++0x之后該實現(xiàn)是線程安全的,C++0x之前仍需加鎖。
class Singleton { private: Singleton() { }; ~Singleton() { }; Singleton(const Singleton&); Singleton& operator=(const Singleton&); public: static Singleton& getInstance() { static Singleton instance; return instance; } };
適配器模式
C++ 適配器模式是一種結(jié)構(gòu)型設(shè)計模式,它允許現(xiàn)有的類在不修改其內(nèi)部結(jié)構(gòu)的情況下在其他類中可用。它使用適配器來將不兼容的接口轉(zhuǎn)換成用于目標(biāo)類的接口。適配器模式使客戶端能夠調(diào)用他們正在使用的接口,而實際上正在使用另一個接口,這個新接口已經(jīng)與客戶端的要求匹配。
#include <iostream> using namespace std; // 定義接口 class Target { virtual void request() = 0; }; // 創(chuàng)建一個需要被適配的類 class Adaptee { void specificRequest(); }; // 創(chuàng)建一個適配器 class Adapter : public Target { Adaptee *adaptee; public: Adapter(Adaptee *adaptee) { this->adaptee = adaptee; } void request() { // 執(zhí)行specificRequest方法 adaptee->specificRequest(); } }; int main() { Adaptee *adaptee = new Adaptee(); Target *target = new Adapter(adaptee); target->request(); return 0; }
外觀模式
在C++中,外觀模式是一種使用來簡化系統(tǒng)接口的模式。它由一個“外觀”類定義,這個類知道要包裝的一系列子系統(tǒng)類??蛻艨梢酝ㄟ^外觀類直接訪問子系統(tǒng)中的功能而不必了解內(nèi)部細(xì)節(jié)。這樣會降低時間和精力,可以減少客戶端訪問子系統(tǒng)的數(shù)量,所以它是一種簡易的方法,用于整合子系統(tǒng)的接口。
Fa?ade模式 class ComputerFacade { private: CPU *cpu; Memory *mem; HardDrive *hd; public: ComputerFacade() { cpu = new CPU(); mem = new Memory(); hd = new HardDrive(); } ~ComputerFacade() { delete cpu; delete mem; delete hd; } void startComputer() { cpu->freeze(); mem->load(BOOT_ADDRESS, hd->read(BOOT_SECTOR, SECTOR_SIZE)); cpu->execute(); } };
代理模式
代理模式(Proxy Pattern)是一種結(jié)構(gòu)型設(shè)計模式,它為另外一個對象提供一個替代或占位符。當(dāng)客戶無法直接訪問另外一個對象時,代理就可以擔(dān)任中間人的角色,這樣,客戶就可以通過代理對象訪問那個對象了。C++ 可以使用代理模式來實現(xiàn)對象的訪問控制,可以使用該模式來管理對象的生命周期,也可以使用該模式來控制對象的訪問,以及在跨平臺上實現(xiàn)方法調(diào)用。
/** * @file proxy.cpp * @brief 代理模式實現(xiàn)示例 * * 代理模式用于在不直接訪問一個對象的情況下提供訪問方式。 * 它通常由真實對象和代理對象代表,其中真實對象處理實際工作,而代理對象只是 * 提供其接口,本文將使用 C++ 代碼來實現(xiàn)代理模式。 */ #include <iostream> // 真實對象基類 class RealObject { public: virtual void doSomething() = 0; }; // 真實對象實現(xiàn)類 class RealObjectImpl : public RealObject { public: virtual void doSomething() { std::cout << "Doing something in RealObjectImpl" << std::endl; } }; // 代理對象基類,保存一個指向 RealObjectImpl // 對象的指針 class ProxyObject { private: RealObject* m_realObject; public: ProxyObject() : m_realObject(nullptr) { m_realObject = new RealObjectImpl(); } ~ProxyObject() { delete m_realObject; m_realObject = nullptr; } // 調(diào)用真實對象的 doSomething() void doSomething() { if(m_realObject != nullptr) { m_realObject->doSomething(); } } }; int main() { ProxyObject proxyObject; proxyObject.doSomething(); return 0; }
橋接模式
C++橋接模式是一種設(shè)計模式,它把抽象和實現(xiàn)分離開來,以便兩者獨立地變化。此模式在不同的編程語言之間創(chuàng)建了一個“橋”,支持平臺無關(guān)性,以實現(xiàn)代碼重用。它通常由抽象類處理,以及一個“管理類”,該類將實現(xiàn)類注入抽象類中。
// Bridge Pattern – C++ #include <iostream> // Abstract class having the implementation for the interface class Shape { public: virtual void draw() = 0; virtual ~Shape(){} }; // Concrete class 1 class Rectangle : public Shape { public: void draw() override { std::cout << "Drawing a rectangle." << std::endl; } }; // Concrete class 2 class Circle : public Shape { public: void draw() override { std::cout << "Drawing a circle." << std::endl; } }; // Bridge between implementation and interface class DrawingAPI { public: virtual void drawCircle(double x, double y, double radius) = 0; virtual void drawRectangle(double x, double y, double width, double height) = 0; virtual ~DrawingAPI() {} }; // Concrete bridge 1 class DrawingAPI1 : public DrawingAPI { public: void drawCircle(double x, double y, double radius) override { std::cout << "API1.circle at " << x << ':' << y << ' ' << radius << std::endl; } void drawRectangle(double x, double y, double width, double height) override { std::cout << "API1.rectangle at " << x << ':' << y << ' ' << width << 'x' << height << std::endl; } }; // Concrete bridge 2 class DrawingAPI2 : public DrawingAPI { public: void drawCircle(double x, double y, double radius) override { std::cout << "API2.circle at " << x << ':' << y << ' ' << radius << std::endl; } void drawRectangle(double x, double y, double width, double height) override { std::cout << "API2.rectangle at " << x << ':' << y << ' ' << width << 'x' << height << std::endl; } }; // Shape implementation using bridge class Shape1 : public Shape { private: DrawingAPI* m_drawingAPI; public: Shape1(DrawingAPI* drawingAPI) : m_drawingAPI(drawingAPI) { } void draw() override { m_drawingAPI->drawCircle(1.0, 2.0, 3.0); } }; // Another shape using same bridge class Shape2 : public Shape { private: DrawingAPI* m_drawingAPI; public: Shape2(DrawingAPI* drawingAPI) : m_drawingAPI(drawingAPI) { } void draw() override { m_drawingAPI->drawRectangle(4.0, 5.0, 6.0, 7.0); } }; // Client int main() { DrawingAPI* drawingAPI = new DrawingAPI1(); Shape* shapes[2] = { new Shape1(drawingAPI), new Shape2(drawingAPI) }; for (Shape* shape : shapes) shape->draw(); return 0; }
模板方法模式
模板方法模式是指定義一個操作中算法的框架,而將算法的一些步驟延遲到子類中實現(xiàn)。模板方法模式使得子類可以不改變算法的結(jié)構(gòu)即可重定義算法的某些特定步驟。 它是一種行為設(shè)計模式,它定義一個算法的模板,將一些計算步驟推遲到子類中。 在C++中,模板方法通常采用繼承機(jī)制實現(xiàn),在基類中定義算法的框架,在子類中實現(xiàn)算法的某些步驟。
//Base class template <class T> class Base { public: void templateMethod() { step1(); step2(); step3(); step4(); } virtual void step1() = 0; virtual void step2() = 0; virtual void step3() = 0; virtual void step4() = 0; }; //Derived class template <class T> class Derived : public Base<T> { public: Derived(T data):m_data(data) {} virtual void step1() { std::cout<<"Step 1 with the data: "<< m_data <<std::endl; } virtual void step2() { std::cout<<"Step 2 with the data: "<< m_data <<std::endl; } virtual void step3() { std::cout<<"Step 3 with the data: "<< m_data <<std::endl; } virtual void step4() { std::cout<<"Step 4 with the data: "<< m_data <<std::endl; } private: T m_data; }; //Client int main() { Base<int> *b = new Derived<int>(10); b->templateMethod(); delete b; return 0; }
策略模式
是一種行為設(shè)計模式,它定義了一組算法,他們可以以相同的接口共享。這種模式使用場景最多的就是在根據(jù)不同的條件選擇不同的行為時,可以使用此模式進(jìn)行解耦,使得你的代碼更加易于維護(hù)和擴(kuò)展,當(dāng)然也要看開發(fā)場景。
#include <iostream> using namespace std; // 抽象策略類 class Strategy { public: virtual void AlgorithmInterface() = 0; // 策略接口 }; // 具體策略類A class ConcreteStrategyA : public Strategy { public: void AlgorithmInterface() { cout<<"using algoritm A"<<endl; } }; // 具體策略類B class ConcreteStrategyB : public Strategy { public: void AlgorithmInterface() { cout<<"using algoritm B"<<endl; } }; // 環(huán)境類Context class Context { private: Strategy * strategy; // 私有策略類指針 public: Context(Strategy * pStrategy) { this->strategy = pStrategy; } void DoAction() { strategy->AlgorithmInterface(); // 使用策略類 } }; // 使用 int main() { Context contextA(new ConcreteStrategyA); // 設(shè)定策略A contextA.DoAction(); Context contextB(new ConcreteStrategyB); // 設(shè)定策略B contextB.DoAction(); return 0; }
觀察者模式
觀察者模式是一種行為型設(shè)計模式,它允許多個“觀察者”被通知某些情況的變化。被觀察的對象(通常稱為被觀察者)將不斷發(fā)出關(guān)于自身狀態(tài)的更新通知,而這些觀察者則偵聽此變化并執(zhí)行相應(yīng)的操作。在C++中,觀察者模式可以使用虛函數(shù),繼承,容器和模板類來實現(xiàn)。
#include <iostream> #include <list> // 抽象被觀察者的接口 class Subject { public: // 注冊觀察者 virtual void Attach(Observer* pObserver) = 0; // 移除觀察者 virtual void Detach(Observer* pObserver) = 0; // 通知所有觀察者 virtual void Notify() = 0; virtual ~Subject(){} }; // 抽象觀察者的接口 class Observer { public: // 響應(yīng)被觀察者的通知 virtual void Update() = 0; virtual ~Observer(){} }; // 被觀察者 class ConcreteSubject : public Subject { public: void Attach(Observer* pObserver) override { m_observers.push_back(pObserver); } void Detach(Observer* pObserver) override { m_observers.remove(pObserver); } void Notify() override { for (auto pObserver : m_observers) pObserver->Update(); } private: std::list<Observer*> m_observers; }; // 具體觀察者 class ConcreteObserver1 : public Observer { public: void Update() override { std::cout << "ConcreteObserver1 Update" << std::endl; } }; class ConcreteObserver2 : public Observer { public: void Update() override { std::cout << "ConcreteObserver2 Update" << std::endl; } }; int main() { ConcreteSubject subject; ConcreteObserver1 observer1; ConcreteObserver2 observer2; subject.Attach(&observer1); subject.Attach(&observer2); subject.Notify(); return 0; }
責(zé)任鏈模式
責(zé)任鏈模式(Chain of Responsibility Pattern)是一種行為設(shè)計模式,它定義了請求的處理者對象之間的關(guān)系,并使多個處理者有機(jī)會處理該請求。當(dāng)發(fā)出一個請求時,請求將沿著鏈條一直傳遞,直到鏈上的某一個處理者決定請求的處理方式。
#include<iostream> using namespace std; //定義抽象類Handler class Handler { protected: Handler* successor; // 定義后繼對象 public: Handler() { successor = NULL; } void SetSuccessor(Handler* suc) { successor = suc; } virtual void HandleRequest() = 0; // 處理請求的抽象方法 }; //實現(xiàn)抽象類Handler class ConcreteHandler1 : public Handler { public: void HandleRequest() { if (successor != NULL) { cout << "ConcreteHandler1 放過請求" << endl; successor->HandleRequest(); } else { cout << "ConcreteHandler1 處理請求"<<endl; } } }; class ConcreteHandler2 : public Handler { public: void HandleRequest() { if (successor != NULL) { cout << "ConcreteHandler2 放過請求" << endl; successor->HandleRequest(); } else { cout << "ConcreteHandler2 處理請求"<<endl; } } }; //Client四 int main(int argc, char* argv[]) { ConcreteHandler1* handler1 = new ConcreteHandler1(); ConcreteHandler2* handler2 = new ConcreteHandler2(); handler1->SetSuccessor(handler2); handler1->HandleRequest(); return 0; }
到此這篇關(guān)于C++常用的11種設(shè)計模式解釋及示例的文章就介紹到這了,更多相關(guān)C++常用的11種設(shè)計模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實現(xiàn)LeetCode(21.混合插入有序鏈表)
這篇文章主要介紹了C++實現(xiàn)LeetCode(21.混合插入有序鏈表),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C++類中const修飾的成員函數(shù)及日期類小練習(xí)
將const修飾的“成員函數(shù)”稱之為const成員函數(shù),const修飾類成員函數(shù),表明在該成員函數(shù)中不能對類的任何成員進(jìn)行修改,下面這篇文章主要給大家介紹了關(guān)于C++類中const修飾的成員函數(shù)及日期類小練習(xí)?的相關(guān)資料,需要的朋友可以參考下2023-01-01