【设计模式】对象创建型模式

对象创建型模式

在这里插入图片描述

系列综述:
来源:该系列是主要参考《大话设计模式》和《设计模式(可复用面向对象软件的基础)》,其他详细知识点拷验来自于各大平台大佬的博客。
总结:汇总篇
如果对你有用,希望关注·点赞·收藏一波。



😊点此到文末惊喜↩︎


对象创建型模式

简单(静态)工厂模式

  1. 核心:将对象的创建过程封装在工厂类中,客户端只需要向工厂类提出请求即可,从而达到客户端与具体产品类之间的解耦合。
  2. 抽象原理
    • 抽象产品基类 :定义了产品的规范,描述了产品的主要特性和功能。
    • 具体产品子类 :继承抽象产品的子类,实现具体产品
    • 静态工厂类 :提供了创建产品的方法,调用者通过该方法来获取产品。
  3. 代码原理
    • 基类:数据成员+虚函数接口(动态基础)
    • 派生类:实现虚函数,即实现类的具体功能
    • 静态工厂类:使用switch结构根据传入的参数动态new对应子类对象
    • 调用:使用基类对象承接静态工厂动态生成对应子类对象赋值给父类
      在这里插入图片描述
  4. 特点:
    • 破坏开闭原则。拓展产品需要修改原工厂内部的逻辑
    • 符合单一职责原则。将对象的创建逻辑和实现的业务逻辑进行了分离
  5. 示例代码
// 产品基类:纯虚函数接口(抽象的规则)+ 规则操作的数据成员
class Operation
{
public:
	// 
    virtual int GetResult() =0;
public:
    double m_Num1;
    double m_Num2;
};
// 算法子类1:重新父类虚函数,实现算法
class OperationAdd:Public Operation
{
public:
    int GetResult(){
    	return m_Num1 + m_Num2;
    }
};
// 算法子类2:重新父类虚函数,实现算法
class OperationSub:Public Operation
{
public:
    int GetResult(){
    	return m_Num1 - m_Num2;
    }
};

// 静态工厂类:根据对象实例化
class OperationFactry
{
public:
    OperationFactry(void);
    ~OperationFactry(void);

	// static主要功能是无需创建类,就可以调用方法
    static Operation CreateOperate(char c )
    {
        switch(c)
        {
        case '+':
            return new OperationAdd;
            break;
		case '-':
			return new OperationSub;
            break;
        }
    }
};

// 调用
Operation oper;// 父类对象
oper = OperationFactry::CreateOperate("+");// 核心:具体的子类转换成父类,进行虚函数的动态调用
oper.m_Num1 = 1;// 给父类对象的数据成员进行赋值
oper.m_Num2 = 2;
double result = oper.GetResult();

工厂方法模式

  1. 抽象原理
    • 抽象产品基类 :定义了产品的规范,描述了产品的主要特性和功能。
    • 具体产品子类 :实现或者继承抽象产品的子类
    • 工厂基类 :定义类别区分的功能接口
    • 具体工厂子类:具体工厂对应生产具体的产品
  2. 代码原理:
    • 定义一个用于创建对象的接口,让子类决定实例化哪一个类
    • 使用抽象解除对于具体实例的耦合,将简单工厂模式中工厂类的分支导致的与对象创建的耦合使用抽象类进行解决
      在这里插入图片描述
  3. 特点
    • 符合单一职责原则和开闭原则
    • 增加系统复杂度和开销,并且大量产品会导致对应工厂类的膨胀
  4. 实现方法
    // 产品类与简单工厂方法相同,工厂方法就是将工厂抽象出来,具体对象由具体对象创建
    ···
    // 工厂方法接口类:根据对象实例化
    class IFactory{
    	virtual Operation* CreateOperate() = 0;
    }
    
    // 工厂子类
    class OperationAddFactory : public IFactory{
     public:
      Operation CreateOperate(){
    		return new OperationAdd();
    	}
    }
    class OperationSubFactory : IFactory{
     public:
      Operation* CreateOperate(){
    		return new OperationSub();
    	}
    }
    
    // 调用
    IFactory *factory = new OperationXXXFactory();// 子转父:具体工厂赋值给抽象工厂
    Operation *oper = factory.CreateOperate();// 子转父:具化的抽象工厂生产具体产品赋值给抽象产品
    oper.m_Num1 = 1;// 给父类对象的数据成员进行赋值
    oper.m_Num2 = 2;
    double result = oper.GetResult();
    

抽象工厂模式

  1. 抽象原理
    • 抽象工厂基类:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
    • 具体工厂类:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
    • 多个抽象产品基类:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
    • 对应的具体产品类:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
  2. 特点
    • 满足开闭原则:当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码。
    • 不满足开闭原则:当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改。
    • 当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。
      在这里插入图片描述
  3. 代码示例
    // 抽象操作类
    class Operation {
    public:
        virtual double getResult(double num1, double num2) = 0;
    };
    // 加法操作类
    class AddOperation : public Operation {
    public:
        double getResult(double num1, double num2) {
            return num1 + num2;
        }
    };
    // 减法操作类
    class SubOperation : public Operation {
    public:
        double getResult(double num1, double num2) {
            return num1 - num2;
        }
    };
    // 乘法操作类
    class MulOperation : public Operation {
    public:
        double getResult(double num1, double num2) {
            return num1 * num2;
        }
    };
    // 除法操作类
    class DivOperation : public Operation {
    public:
        double getResult(double num1, double num2) {
            if (num2 == 0) {
                throw "除数不能为0";
            }
            return num1 / num2;
        }
    };
    // 抽象工厂类:具有所有的工厂实现接口
    class Factory {
    public:
        virtual Operation* createAdd() = 0;
        virtual Operation* createSub() = 0;
        virtual Operation* createMul() = 0;
        virtual Operation* createDiv() = 0;
    };
    
    // 加减工厂类
    class AddSubFactory : public Factory {
    public:
        Operation* createAdd() {
            return new AddOperation();
        }
        Operation* createSub() {
            return new SubOperation();
        }
        Operation* createMul() { return nullptr; }
        Operation* createDiv() { return nullptr; }
    };
    
    // 乘除工厂类
    class MulDivFactory : public Factory {
    public:
        Operation* createAdd() { return nullptr; }
        Operation* createSub() { return nullptr; }
        Operation* createMul() {
            return new MulOperation();
        }
        Operation* createDiv() {
            return new DivOperation();
        }
    };
    
    // 调用
    Factory* factory = new AddSubFactory(); // 创建加减工厂实例
    // 创建加法操作实例并进行计算
    Operation* add = factory->createAdd();
    double result1 = add->getResult(1, 2);
    cout << "1 + 2 = " << result1 << endl;
    // 创建减法操作实例并进行计算
    Operation* sub = factory->createSub();
    double result2 = sub->getResult(4, 2);
    cout << "4 - 2 = " << result2 << endl;
    // 释放资源
    delete add;
    delete sub;
    delete factory;
    

单例模式

  1. 定义:保证一个类只能产生一个实例,并提供一个访问它的全局访问点。
    • 私有化的构造函数,保证类外无法实例化
    • 私有化静态的类对象,保证类只有一个实例
    • 公开静态的成员函数,作为类的全局访问点
  2. 特点
    • 优点:单例类对象具有唯一性,减少了内存的开销,尤其是频繁的创建和销毁实例。
    • 缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
  3. 类型
    • 懒汉式:适合单线程且单例对象不经常使用的情况
      • 单线程:在多线程下,不是线程安全的,同步锁会影响性能。
      • 不经常使用:单例类的实例的初始化会延迟lazy到第一次被引用时候,可以避免资源浪费
    #include <iostream>
    #include <mutex>	// 互斥锁头文件
    using namespace std;
    
    class SinglePattern {
      public:
      	// 1. 公共实例化接口:返回对象指针来保证对象的唯一性
      	static SinglePattern *GetInstance() {
      		// 2. 线程安全:lock_guard会在构造函数中加锁,
      		// 			在析构函数中自动解锁
      		lock_guard<mutex> lock(mtx);
      		// 3. 延迟绑定:类的实例化延迟到第一次使用时候
    		if (instance == nullptr) {
    			instace = new SinglePattern();
    		}
    		return instance;
    	}
      private:
      	static SinglePattern *instance;
      	static mutex mtx;
      	SinglePattern(const SinglePattern &single) = delete;
      	SinglePattern& operator=(const SinglePattern&) = delete;
      	SinglePattern() {}
      
    };
    // 类内静态变量需要紧跟在类外进行初始化操作
    SinglePattern* SinglePattern::instance = nullptr;
    mutex SinglePattern::mtx;
    
    int main() {
       Singleton* s1 = Singleton::getInstance();
       return 0;
    }
    
    • 饿汉式:适用于多线程且单例对象经常使用的情况。
      • 线程安全:无需担心多线程下的执行乱序问题
      • 经常使用:单例对象在未使用时,就被初始化
    class SinglePattern {
      public:
      	// 1. 公共实例化接口:通过返回对象的引用避免拷贝构造
      	static SinglePattern& GetInstance() {
      		// 2. 线程安全的保证:静态局部变量只会被原子的初始化一次
    		static SinglePattern instance;
    		return instance;
    	}
      private:
      	// 3. 保证实例的唯一性:禁止默认构造、拷贝构造和拷贝赋值
      	SinglePattern();
      	SinglePattern(const SinglePattern &single) = delete;
      	SinglePattern& operator=(const SinglePattern&) = delete;
      	// delete相比private可以避免友元函数和成员函数的访问
    }
    
    int main() {
    	// 获取单例对象的引用
    	SinglePattern& single_instance = SinglePattern::GetInstance();
    }
    

Builder建造者/生成器模式

  1. 核心:
    • 执行函数流相同,但是执行函数的参 数不同,使得同样的构建过程可以创建不同的表示
    • 将一个复杂对象的构建表示分离,使得同样的构建过程可以创建不同的表示
    • 适合场景:当一个类的构造函数参数超过4个,而且这些参数有些是可选的时
  2. 抽象原理
    • 产品(Product):描述产品,包括产品的属性对应的set函数
    • 抽象建造者基类(Builder):描述建造流程,主要包含私有的建造对象建造对象流程的纯虚函数返回建造对象函数
    • 具体建造者类(ConreteBuilder):具体化对象的各个组成部分的创建,包含产品属性set的虚函数
    • 导演类(Director):负责指导建造过程,包含返回建造对象的函数,其中是抽象建造流程
      在这里插入图片描述
  3. 优点
    • S符合单一职责原则:隔离复杂对象的创建和表示,可以对复杂对象的创建过程进行更精细的控制。
    • O符合开放封闭原则
      • 对拓展开放:建造者模式将对象的构建过程分步进行,增加新的建造者不会影响现有的系统结构。
      • 对修改封闭:通过具体建造类可以隐藏复杂对象的创建细节
  4. 缺点
    • 增加了系统中类和对象的个数,可能会增加系统的复杂度和理解难度。
    • 适用于构建复杂对象,如果构建简单对象会增加系统复杂度
  5. 示例代码
    // 产品描述
    class Product{
    public:
        void setMainBoard(const string& main_Board) { 
        	main_Board_= main_Board; 
        }
        void setRAM(const string& cpu) { cpu_= cpu; }
        void setCPU(const string& ram) { ram_= ram; }
    private:
        string main_Board_;
        string cpu_;
        string ram_;
    };
    
    // 抽象建造者
    class Builder{
     public:
     	// 建造流程
    	virtual void AddMainBoard() = 0;// 装配主板
    	virtual void AddCpu() = 0;		// 装配CPU
    	virtual void AddGpu() = 0;		// 装配GPU
    	// 返回建造对象
    	Product getComputer() {
    		return m_computer;
    	}
     protected:
    	Product computer_; // 电脑产品
    };
    
    // 坠机堡垒华硕电脑 建造者
    class ASUABuilder : public Builder{
     public:
    	// 装配主板
    	virtual void AddMainBoard() {
    		m_computer.setMainBoard("B760");
    	}
    	 	// 装配cpu
    	virtual void AddCpu() {
    		m_computer.setCPU("Intel 酷睿i7-8700K");
    	}
    	// 装配内存
    	virtual void AddRAM() {
    	m_computer.setRAM("三星DDR4 2666mhz 16G");
    	}
    };
    // 人傻钱多戴尔电脑 建造者
    class HPBuilder : public Builder{
     public:
    	// 装配主板
    	virtual void AddMainBoard() {
    		m_computer.setMainBoard("B760");
    	}
     	// 装配cpu
    	virtual void AddCpu() {
    		m_computer.setCPU("Intel 酷睿i7-8750h");
    	}
    	// 装配内存
    	virtual void AddRAM() {
    	m_computer.setRAM("海力士DDR4 2666mhz 8G");
    	}
    };
    
    // 导演类(负责指导建造过程)
    class Director{
    public:
        Product build(Builder& builder){
            builder.AddMainBoard();
            builder.AddCPU();
            builder.AddRAM();
            return builder.getComputer();
        }
    };
    
    // 使用示例
    int main(){
        ASUABuilder asus_builder;
        HPBuilder hp_builder;
        Director director;
        Product asus_computer = director.build(asus_builder);
        Product hp_computer = director.build(hp_builder);
        return 0;
    }
    


少年,我观你骨骼清奇,颖悟绝伦,必成人中龙凤。
秘籍(点击图中书籍)·有缘·赠予你


🚩点此跳转到首行↩︎

参考博客

  1. 秒懂设计模式之建造者模式(Builder pattern)
  2. 单例模式(Singleton)的同步锁synchronized
  3. 设计模式之Builder模式
  4. 待定引用
  5. 待定引用
  6. 待定引用
  7. 待定引用
  8. 待定引用
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逆羽飘扬

如果有用,请支持一下。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值