C++常用的11種設(shè)計模式解釋及示例代碼詳解
c++常用的設(shè)計模式包括單例模式、工廠模式、抽象工廠模式、適配器模式、裝飾者模式、代理模式、外觀模式、橋接模式、組合模式、享元模式、觀察者模式和命令模式等。使用設(shè)計模式的好處:提高代碼的可讀性和可維護性;將常見的設(shè)計問題隔離程序的業(yè)務(wù)邏輯;重用已有的實現(xiàn);消除重復(fù)代碼;消除手動調(diào)整代碼以達到正確邏輯的所有痛苦。
工廠模式
C++工廠模式是一種模式,它是一種創(chuàng)建對象的有效方法。它允許我們使用一個類來負責(zé)創(chuàng)建實現(xiàn)特定接口的不同具體類的實例,而無需明確指定該實例的具體類。通過抽象出一個工廠類來負責(zé)每個子類的實例化,使得代碼的可維護性大大增加。這種模式也使得添加新類型的實例變得容易,只要擴展工廠類即可。
#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):單例實例在第一次被使用時才進行初始化,這叫做延遲初始化,然而可能存在內(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標準下,《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)換成用于目標類的接口。適配器模式使客戶端能夠調(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)部細節(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++中,模板方法通常采用繼承機制實現(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ù)不同的條件選擇不同的行為時,可以使用此模式進行解耦,使得你的代碼更加易于維護和擴展,當(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)系,并使多個處理者有機會處理該請求。當(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ù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07
C++類中const修飾的成員函數(shù)及日期類小練習(xí)
將const修飾的“成員函數(shù)”稱之為const成員函數(shù),const修飾類成員函數(shù),表明在該成員函數(shù)中不能對類的任何成員進行修改,下面這篇文章主要給大家介紹了關(guān)于C++類中const修飾的成員函數(shù)及日期類小練習(xí)?的相關(guān)資料,需要的朋友可以參考下2023-01-01

