首页 > 编程语言 >C++常用设计模式详解

C++常用设计模式详解

时间:2024-10-10 18:54:17浏览次数:9  
标签:void 观察者 C++ class 详解 模式 override 设计模式 public

前言:本文详细解释几种常用的C++设计模式,都是平时项目中用的比较多的。本文针对每种设计模式都给出了示例,让你跟着代码彻底搞懂设计模式。

Tips:如果是准备面试,不需要知道所有的设计模式,要深入理解下面几种常用即可,因为面试官会先问你了解哪些设计模式,然后从你了解的里面挑一个深问,而且很有可能还会让你手撕出来。而且,最好提前准备一下自己的项目中哪里用到了你说的设计模式,面试官也可能会问。

文章目录


C++常用设计模式

单例模式

单例模式确保一个类只有一个实例,并提供一个全局访问点来访问该实例。主要用于控制全局资源,如日志管理器、线程池、配置管理器等。

实现方式:

  • 构造函数为私有,防止外部创建对象。
  • 提供一个静态方法,负责创建或获取该类的唯一实例。
  • 确保线程安全性。
class Singleton {
private:
    Singleton() {}

public:
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }

    // 禁止拷贝和赋值操作
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

C++11规定了局部静态变量在多线程条件下的初始化行为,要求编译器保证了局部静态变量的线程安全性。这样,只有当第一次访问getInstance()方法时才创建实例。C++11之后该实现是线程安全的,C++11之前仍需加锁。

工厂模式

用于创建对象(产品类)的接口,而不暴露对象创建的具体逻辑。适合于需要创建多个相似对象的场景,比如:图形界面组件、数据库连接。

简单工厂模式

建⽴⼀个⼯⼚类,对实现了同⼀接⼝的⼀些类(产品类)进⾏实例的创建。简单⼯⼚模式的实质是由⼀个⼯⼚类根据传⼊的参数,动态决定应该创建哪⼀个产品类(这些产品类继承⾃⼀个⽗类或接⼝)的实例。

// 产品类(抽象类,不能实例化)
class Product {
public:
    virtual void show() = 0;
};

class ConcreteProductA : public Product {
public:
    void show() override { std::cout << "Product A\n"; }
};

class ConcreteProductB : public Product {
public:
    void show() override { std::cout << "Product B\n"; }
};

// ⼯⼚类
class Factory {
public:
	Product* product(const string str){
		if (str == "productA")
			return new ConcreteProductA();
		if (str == "productB")
			return new ConcreteProductB();
		return nullptr;
	};
};

抽象工厂模式

为了进⼀步解耦,在简单⼯⼚的基础上发展出了抽象⼯⼚模式,即连⼯⼚都抽象出来,实现了进⼀步代码解耦。通过定义一个用于创建对象的接口,让工厂子类决定实例化哪个类。工厂模式的核心思想是将对象的创建和使用分离,以提高灵活性和扩展性。

实现方式:

  • 定义一个工厂基类,声明一个创建产品的接口。
  • 工厂子类实现这个接口,负责具体产品的创建。
class Product {
public:
    virtual void show() = 0;
};

class ConcreteProductA : public Product {
public:
    void show() override { std::cout << "Product A\n"; }
};

class ConcreteProductB : public Product {
public:
    void show() override { std::cout << "Product B\n"; }
};

class Factory {
public:
    virtual Product* createProduct() = 0;
};

class ConcreteFactoryA : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProductA();
    }
};

class ConcreteFactoryB : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProductB();
    }
};

观察者模式

定义了对象之间一对多的依赖关系,让多个观察对象同时监听⼀个被观察对象,被观察对象状态发⽣变化时,会通知所有的观察对象,使他们能够更新⾃⼰的状态。该模式常用于事件驱动系统、消息发布-订阅系统。

观察者模式中存在两种⻆⾊:

  • 观察者:内部包含被观察者对象,当被观察者对象的状态发⽣变化时,更新自己的状态。(接收通知更新状态)
  • 被观察者:内部包含了所有观察者对象,当状态发⽣变化时通知所有的观察者更新自己的状态。(发送通知)

实现方式:

  • 定义一个被观察者(Subject)接口,允许添加、删除观察者。
  • 定义观察者接口,声明更新方法。
  • 被观察者在状态发生变化时,通知所有观察者调用更新方法。
// 观察者
class Observer {
public:
    virtual void update(int value) = 0;
};

class ConcreteObserver : public Observer {
private:
    int observerValue;
    
public:
	// 被观察者对象的状态发⽣变化时,更新自己的状态
    void update(int value) override {
        observerValue = value;
        std::cout << "Observer value updated to " << observerValue << "\n";
    }
};

// 被观察者
class Subject {
private:
    std::vector<Observer*> observers;	// 存放所有观察者
    int state;

public:
    void attach(Observer* observer) {
        observers.push_back(observer);
    }

    void setState(int value) {
        state = value;
        notify();
    }
	
	// 通知所有的观察者更新自己的状态
    void notify() {
        for (Observer* observer : observers) {
            observer->update(state);
        }
    }
};

装饰器模式

装饰器模式允许向现有对象动态地添加行为,而不影响其他同类对象。该模式通常用于给对象增加功能,同时保持对象的结构灵活可扩展。

实现方式:

  • 定义一个组件接口,声明可以被装饰的操作。
  • 具体组件类实现接口,执行基本操作。
  • 装饰器类持有组件的引用,并在执行基本操作时添加新的功能。
// 组件接口
class Component {
public:
    virtual void operation() = 0;
};

// 具体组件
class ConcreteComponent : public Component {
public:
    void operation() override {
        std::cout << "ConcreteComponent operation\n";
    }
};

// 抽象装饰类
class Decorator : public Component {
protected:
    Component* component;

public:
    Decorator(Component* comp) : component(comp) {}

    void operation() override {
        component->operation();
    }
};

// 具体装饰类
class ConcreteDecorator : public Decorator {
public:
    ConcreteDecorator(Component* comp) : Decorator(comp) {}

    void operation() override {
        Decorator::operation();
        std::cout << "ConcreteDecorator added operation\n";
    }
};

// 创建一个具体组件
Component* component = new ConcreteComponent();
// 装饰组件
Component* decorator = new ConcreteDecorator(component);

解释:通过具体装饰类传入原对象,并重写操作函数 operation() 来实现对象的功能扩展,ConcreteDecorator::operation 先执行对象原操作,再执行新扩展的功能。

策略模式

策略模式定义了一系列算法,将每个算法封装到一个独立的类中,使得它们可以相互替换。此模式允许算法的变化独立于使用它的客户端。常用于:算法选择、支付方式选择等。

实现方式:

  • 定义一个抽象策略接口,声明策略的操作。
  • 策略实现类负责具体的算法。
  • 上下文类负责持有策略并执行操作。
// 抽象策略接口
class Strategy {
public:
    virtual void execute() = 0;
};

// 策略实现类A
class ConcreteStrategyA : public Strategy {
public:
    void execute() override {
        std::cout << "Executing strategy A\n";
    }
};
// 策略实现类B
class ConcreteStrategyB : public Strategy {
public:
    void execute() override {
        std::cout << "Executing strategy B\n";
    }
};

// 上下文类
class Context {
private:
    Strategy* strategy;

public:
    Context(Strategy* strategy) : strategy(strategy) {}
	
	// 选取某种策略
    void setStrategy(Strategy* newStrategy) {
        strategy = newStrategy;
    }
	
	// 执行选取策略的操作
    void executeStrategy() {
        strategy->execute();
    }
};

代理模式

代理模式为其他对象提供一个代理,以控制对这个对象的访问。常见的应用场景包括虚拟代理(延迟加载)、远程代理(为远程对象提供本地代理),以及保护代理(控制对象的访问权限)。

实现方式:

  • 定义一个接口,声明需要被代理的操作。
  • 代理类实现接口,负责控制实际对象的访问。
  • 实际对象类实现接口,执行具体操作。
class Subject {
public:
    virtual void request() = 0;
};

// 实际对象类
class RealSubject : public Subject {
public:
    void request() override {
        std::cout << "RealSubject handling request\n";
    }
};

// 代理类
class Proxy : public Subject {
private:
    RealSubject* realSubject;

public:
    Proxy() : realSubject(nullptr) {}

    ~Proxy() {
        delete realSubject;
    }

    void request() override {
        if (!realSubject) {
            realSubject = new RealSubject();
        }
        std::cout << "Proxy handling request, forwarding to RealSubject...\n";
        realSubject->request();
    }
};

标签:void,观察者,C++,class,详解,模式,override,设计模式,public
From: https://blog.csdn.net/weixin_46571171/article/details/142756800

相关文章

  • c++(自创游戏6)
    1.自创游戏6作者在家里看见了一本书,书名叫:小学生趣味编程,大人也可以看,作者在上面找到了,if,下面是作者自己创作的小游戏,想玩的复制一下就行了,上代码。#include<bits/stdc++.h>#include<windows.h>usingnamespacestd;intmain(){inta;cout<<"请开始游玩if游戏"......
  • 轻松入门:Maven核心功能详解
    Whitegraces:个人主页......
  • Cisco IS-IS ATT-Bit 详解 | ATT 位过滤
    注:机翻,未校。IS-ISAttachedBitIS-IS附加位PostedonNovember22,2016Overview概述AswehavegonethroughbasicIS-ISconfigurationandverification,let’sdiscoveranotherIS-ISinformationregardingIS-ISattachedbit.WhenweuseIS-ISasaro......
  • 实验1 现代C++编程初体验
    任务1://现代C++标准库、算法库体验//本例用到以下内容://1.字符串string,动态数组容器类vector、迭代器//2.算法库:反转元素次序、旋转元素//3.函数模板、const引用作为形参#include<iostream>#include<string>#include<vector>#include<algorithm>usin......
  • c++初始化列表构造
      #include<iostream>#include<string>usingnamespacestd;classCar{public: stringbrand; intyear; stringtype; //无参构造函数 Car(){ cout<<"无参构造函数"<<endl; } //带一个参数的构造函数 Car(stringb) { cout<<&qu......
  • 《C++代码热更新:为高效开发注入新活力》
    一、引言在软件开发的过程中,我们常常面临着这样的挑战:当程序已经部署到生产环境后,发现了一些需要紧急修复的bug或者需要添加新的功能。传统的方法是停止程序运行,进行代码修改,然后重新编译、部署,这个过程不仅耗时,还可能会影响到用户的使用体验。而代码热更新技术的出现,为......
  • 《C++与简单人工智能算法:开启智能编程之旅》
    一、引言在当今科技飞速发展的时代,人工智能已经成为了一个热门话题。从智能手机的语音助手到自动驾驶汽车,人工智能技术正在逐渐改变我们的生活。而C++作为一种高效、强大的编程语言,也可以用来实现简单的人工智能算法。本文将带你探索在C++中如何实现一个简单的人工智能算......
  • php设计模式(二)结构
    适配器模式(Adapter):结合两个不兼容的接口。GoF定义:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作<?phpclassmessage{publicfunctionsend(){echo'faxiaoix';}publicfunctio......
  • Linux中提示:/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.18' not found 的解决
    一、查看gcc版本中包含哪些库#1.终端中输入如下命令:strings/usr/lib64/libstdc++.so.6|grepGLIBC#2.显示如下:===============================================GLIBCXX_3.4GLIBCXX_3.4.1GLIBCXX_3.4.2GLIBCXX_3.4.3GLIBCXX_3.4.4GLIBCXX_3.4.5GLIBCXX_3.4.6GLIBC......
  • mysql数据库--行级锁,间隙锁和临键锁详解
    转载链接地址:MySQL数据库——锁-行级锁(行锁、间隙锁和临键锁)介绍行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。对于行级......