C++常用的11种设计模式解释及示例

简介: C++常用的11种设计模式解释及示例

c++常用的设计模式包括单例模式、工厂模式、抽象工厂模式、适配器模式、装饰者模式、代理模式、外观模式、桥接模式、组合模式、享元模式、观察者模式和命令模式等。使用设计模式的好处:提高代码的可读性和可维护性;将常见的设计问题隔离程序的业务逻辑;重用已有的实现;消除重复代码;消除手动调整代码以达到正确逻辑的所有痛苦。


工厂模式


C++工厂模式是一种模式,它是一种创建对象的有效方法。它允许我们使用一个类来负责创建实现特定接口的不同具体类的实例,而无需明确指定该实例的具体类。通过抽象出一个工厂类来负责每个子类的实例化,使得代码的可维护性大大增加。这种模式也使得添加新类型的实例变得容易,只要扩展工厂类即可。


#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 是设计模式的一种,其特点是只提供唯一一个类的实例,具有全局变量的特点,在任何位置都可以通过接口获取到那个唯一实例。


class Singleton
{
    private:
        static Singleton* instance;
        Singleton() { }
     public:
        static Singleton* getInstance() {
            if(instance == nullptr)
                instance = new Singleton();
            return instance;
        }
};
 Singleton* Singleton::instance = nullptr;


以上只是一种通用实现教学版,即懒汉版(Lazy Singleton):单例实例在第一次被使用时才进行初始化,这叫做延迟初始化,然而可能存在内存泄漏的风险,且这个代码在单线程环境下是正确无误的,但是当拿到多线程环境下时这份代码就会出现race condition。


C++11规定了local static在多线程条件下的初始化行为,要求编译器保证了内部静态变量的线程安全性。在C++11标准下,《Effective C++》提出了一种更优雅的单例模式实现,使用函数内的 local static 对象。这样,只有当第一次访问getInstance()方法时才创建实例。这种方法也被称为Meyers' Singleton。C++0x之后该实现是线程安全的,C++0x之前仍需加锁。


class Singleton
{
private:
  Singleton() { };
  ~Singleton() { };
  Singleton(const Singleton&);
  Singleton& operator=(const Singleton&);
public:
  static Singleton& getInstance() 
        {
    static Singleton instance;
    return instance;
  }
};


适配器模式


C++ 适配器模式是一种结构型设计模式,它允许现有的类在不修改其内部结构的情况下在其他类中可用。它使用适配器来将不兼容的接口转换成用于目标类的接口。适配器模式使客户端能够调用他们正在使用的接口,而实际上正在使用另一个接口,这个新接口已经与客户端的要求匹配。


#include <iostream> 
using namespace std; 
 // 定义接口 
class Target 
{ 
    virtual void request() = 0; 
}; 
 // 创建一个需要被适配的类 
class Adaptee 
{ 
    void specificRequest(); 
}; 
 // 创建一个适配器 
class Adapter : public Target 
{ 
    Adaptee *adaptee; 
 public: 
    Adapter(Adaptee *adaptee) { this->adaptee = adaptee; } 
    void request() 
    { 
        // 执行specificRequest方法 
        adaptee->specificRequest(); 
    } 
}; 
 int main() 
{ 
    Adaptee *adaptee = new Adaptee(); 
    Target *target = new Adapter(adaptee); 
    target->request(); 
    return 0; 
}


外观模式


在C++中,外观模式是一种使用来简化系统接口的模式。它由一个“外观”类定义,这个类知道要包装的一系列子系统类。客户可以通过外观类直接访问子系统中的功能而不必了解内部细节。这样会降低时间和精力,可以减少客户端访问子系统的数量,所以它是一种简易的方法,用于整合子系统的接口。


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)是一种结构型设计模式,它为另外一个对象提供一个替代或占位符。当客户无法直接访问另外一个对象时,代理就可以担任中间人的角色,这样,客户就可以通过代理对象访问那个对象了。C++ 可以使用代理模式来实现对象的访问控制,可以使用该模式来管理对象的生命周期,也可以使用该模式来控制对象的访问,以及在跨平台上实现方法调用。


/**
 * @file proxy.cpp
 * @brief 代理模式实现示例
 *
 * 代理模式用于在不直接访问一个对象的情况下提供访问方式。
 * 它通常由真实对象和代理对象代表,其中真实对象处理实际工作,而代理对象只是
 * 提供其接口,本文将使用 C++ 代码来实现代理模式。
  */
 #include <iostream>
 // 真实对象基类
class RealObject 
{
 public:
  virtual void doSomething() = 0;
};
 // 真实对象实现类
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;
  }
   // 调用真实对象的 doSomething()
  void doSomething() 
  {
   if(m_realObject != nullptr) 
   {
    m_realObject->doSomething();
   }
  }
};
 int main() 
{
 ProxyObject proxyObject;
 proxyObject.doSomething();
  return 0;
}


桥接模式


C++桥接模式是一种设计模式,它把抽象和实现分离开来,以便两者独立地变化。此模式在不同的编程语言之间创建了一个“桥”,支持平台无关性,以实现代码重用。它通常由抽象类处理,以及一个“管理类”,该类将实现类注入抽象类中。


// 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; 
}


模板方法模式


模板方法模式是指定义一个操作中算法的框架,而将算法的一些步骤延迟到子类中实现。模板方法模式使得子类可以不改变算法的结构即可重定义算法的某些特定步骤。 它是一种行为设计模式,它定义一个算法的模板,将一些计算步骤推迟到子类中。 在C++中,模板方法通常采用继承机制实现,在基类中定义算法的框架,在子类中实现算法的某些步骤。


//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; 
}


策略模式


是一种行为设计模式,它定义了一组算法,他们可以以相同的接口共享。这种模式使用场景最多的就是在根据不同的条件选择不同的行为时,可以使用此模式进行解耦,使得你的代码更加易于维护和扩展,当然也要看开发场景。


#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; 
    } 
}; 
// 环境类Context 
 class Context  
{ 
private: 
    Strategy * strategy;    // 私有策略类指针 
public: 
    Context(Strategy * pStrategy) 
    { 
        this->strategy = pStrategy; 
    } 
    void DoAction() 
    { 
        strategy->AlgorithmInterface();    // 使用策略类 
    } 
}; 
 // 使用
int main() 
{ 
    Context contextA(new ConcreteStrategyA); // 设定策略A 
    contextA.DoAction();  
    Context contextB(new ConcreteStrategyB);  // 设定策略B 
    contextB.DoAction(); 
    return 0; 
}


观察者模式


观察者模式是一种行为型设计模式,它允许多个“观察者”被通知某些情况的变化。被观察的对象(通常称为被观察者)将不断发出关于自身状态的更新通知,而这些观察者则侦听此变化并执行相应的操作。在C++中,观察者模式可以使用虚函数,继承,容器和模板类来实现。


#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:
    // 响应被观察者的通知
    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;
}


责任链模式


责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它定义了请求的处理者对象之间的关系,并使多个处理者有机会处理该请求。当发出一个请求时,请求将沿着链条一直传递,直到链上的某一个处理者决定请求的处理方式。


#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; // 处理请求的抽象方法 
}; 
 //实现抽象类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; 
}


其他资源


C++常用的11种设计模式_CBoy_JW的博客-CSDN博客_c++设计模型


设计模式八大原则_伐尘的博客-CSDN博客_设计模式八大原则


设计模式的八大原则_Y仟仟的博客-CSDN博客_设计模式八大原则


C++几种常用设计模式_c++设计模式_lTimej的博客-CSDN博客


C++ 有哪些经常用到的设计模式? - 知乎


C++ 有哪些常用又简单的设计模式? - 知乎


C++各类设计模式及实现详解 - 知乎


C++几种常用设计模式_c++设计模式_lTimej的博客-CSDN博客


C++设计模式(全23种)_momohola的博客-CSDN博客_c++设计模式

相关文章
|
6月前
|
算法 C++ 容器
C++中模板函数以及类模板的示例(template)
C++中模板函数以及类模板的示例(template)
|
5月前
|
Ubuntu C++ Docker
Docker的基本指令和HTML/PYTHON/C++的简单创建示例
Docker的基本指令和HTML/PYTHON/C++的简单创建示例
|
6月前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
|
3月前
|
设计模式 存储 Java
掌握Java设计模式的23种武器(全):深入解析与实战示例
掌握Java设计模式的23种武器(全):深入解析与实战示例
|
4月前
|
设计模式 C++
C++一分钟之-设计模式:工厂模式与抽象工厂
【7月更文挑战第14天】设计模式是解决软件设计问题的通用方案。工厂模式与抽象工厂模式是创建型模式,用于对象创建而不暴露创建逻辑。工厂模式推迟实例化到子类,但过度使用会增加复杂性。抽象工厂则创建相关对象族,但过度抽象可能造成不必要的复杂度。两者均应按需使用,确保设计灵活性。代码示例展示了C++中如何实现这两种模式。
41 3
|
4月前
|
设计模式 安全 C++
C++一分钟之-C++中的设计模式:单例模式
【7月更文挑战第13天】单例模式确保类只有一个实例,提供全局访问。C++中的实现涉及线程安全和生命周期管理。基础实现使用静态成员,但在多线程环境下可能导致多个实例。为解决此问题,采用双重检查锁定和`std::mutex`保证安全。使用`std::unique_ptr`管理生命周期,防止析构异常和内存泄漏。理解和正确应用单例模式能提升软件的效率与可维护性。
51 2
|
6月前
|
设计模式 开发框架 算法
C++中的设计模式:基本概念与应用
C++中的设计模式:基本概念与应用
59 2
|
6月前
|
编解码 JavaScript 前端开发
【专栏】介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例
【4月更文挑战第29天】本文介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例。Base64编码将24位二进制数据转换为32位可打印字符,用“=”作填充。文中展示了各语言的编码解码代码,帮助开发者理解并应用于实际项目。
132 1
|
6月前
|
安全 算法 程序员
探索C++的魅力:语言特性、编程实践及代码示例
C++是广泛应用的编程语言,尤其在系统级编程、应用开发、游戏和嵌入式系统中广泛使用。其主要特性包括:面向对象编程(封装、继承、多态),泛型编程(通过模板实现代码复用和类型安全),以及丰富的标准库和第三方库。在编程实践中,需注意内存管理、异常处理和性能优化。示例代码展示了面向对象和泛型编程,如类的继承和泛型函数的使用。C++的内存管理和库支持使其在解决复杂问题时具有高效和灵活性。
|
6月前
|
设计模式 算法 中间件
【C++ 可调用对象的应用】C++设计模式与现代编程技巧:深入可调用对象的世界
【C++ 可调用对象的应用】C++设计模式与现代编程技巧:深入可调用对象的世界
211 1