😏★,°:.☆( ̄▽ ̄)/$:.°★ 😏
这篇文章主要介绍设计模式:建造者、原型、单例。
学其所用,用其所学。——梁启超
欢迎来到我的博客,一起学习,共同进步。
喜欢的朋友可以关注一下,下次更新不迷路🥞
文章目录
- :smirk:1. 建造者模式
- :blush:2. 原型模式
- :satisfied:3. 单例模式
😏1. 建造者模式
建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式的结构包含以下几个角色:
- 抽象建造者(AbstractBuilder):创建一个Product对象的各个部件指定的抽象接口;
- 具体建造者(ConcreteBuilder):实现AbstractBuilder的接口,实现各个部件的具体构造方法和装配方法,并返回创建结果。
- 产品(Product):具体的产品对象
- 指挥者(Director): 构建一个使用Builder接口的对象,安排复杂对象的构建过程,客户端一般只需要与Director交互,指定建造者类型,然后通过构造函数或者setter方法将具体建造者对象传入Director。它主要作用是:隔离客户与对象的生产过程,并负责控制产品对象的生产过程
#include <iostream>
#include <string>
// 产品类
class Product {
public:
void setPartA(const std::string& partA) {
partA_ = partA;
}
void setPartB(const std::string& partB) {
partB_ = partB;
}
void setPartC(const std::string& partC) {
partC_ = partC;
}
void show() {
std::cout << "Product parts: " << partA_ << ", " << partB_ << ", " << partC_ << std::endl;
}
private:
std::string partA_;
std::string partB_;
std::string partC_;
};
// 抽象建造者类
class Builder {
public:
virtual void buildPartA() = 0;
virtual void buildPartB() = 0;
virtual void buildPartC() = 0;
virtual Product* getProduct() = 0;
};
// 具体建造者类 A
class ConcreteBuilderA : public Builder {
public:
void buildPartA() override {
product_->setPartA("PartA of Product A");
}
void buildPartB() override {
product_->setPartB("PartB of Product A");
}
void buildPartC() override {
product_->setPartC("PartC of Product A");
}
Product* getProduct() override {
return product_;
}
private:
Product* product_ = new Product();
};
// 指挥者类
class Director {
public:
void construct(Builder* builder) {
builder->buildPartA();
builder->buildPartB();
builder->buildPartC();
}
};
int main() {
Director director;
ConcreteBuilderA builderA;
director.construct(&builderA);
Product* productA = builderA.getProduct();
productA->show();
delete productA;
return 0;
}
适用环境:
- 需要生成的产品对象有复杂的内部结构(通常包含多个成员变量);
- 产品对象内部属性有一定的生成顺序;
- 同一个创建流程适用于多种不同的产品。
😊2. 原型模式
原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
原型式的结构包含以下几个角色:
- 抽象原型类(AbstractPrototype):声明克隆clone自身的接口
- 具体原型类(ConcretePrototype):实现clone接口
- 客户端(Client):客户端中声明一个抽象原型类,根据客户需求clone具体原型类对象实例
原型模式可以说是“复制”,即克隆,但这个复制不是代码的复制,而是将对象包含的所有属性都创建一份拷贝。但不同的复制操作,可能会产生两种不同的拷贝,即浅拷贝和深拷贝。
#include <iostream>
// 原型基类
class Prototype {
public:
virtual Prototype* clone() = 0;
virtual void show() = 0;
};
// 具体原型类 A
class ConcretePrototypeA : public Prototype {
public:
Prototype* clone() override {
return new ConcretePrototypeA(*this);
}
void show() override {
std::cout << "ConcretePrototypeA" << std::endl;
}
};
// 具体原型类 B
class ConcretePrototypeB : public Prototype {
public:
Prototype* clone() override {
return new ConcretePrototypeB(*this);
}
void show() override {
std::cout << "ConcretePrototypeB" << std::endl;
}
};
int main() {
ConcretePrototypeA prototypeA;
Prototype* clonedA = prototypeA.clone();
clonedA->show();
delete clonedA;
ConcretePrototypeB prototypeB;
Prototype* clonedB = prototypeB.clone();
clonedB->show();
delete clonedB;
return 0;
}
适用环境:
- 当创建新的对象实例较为复杂时,原型模式可以简化创建过程;
- 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少几个的组合状态,通过复制原型对象得到新实例,比通过使用构造函数创建一个新实例会更加方便。
😆3. 单例模式
单例模式是指在整个系统生命周期内,保证一个类只能产生一个实例,确保该类的唯一性。
单例模式可以保证线程安全,即给共享的资源加把锁,保证每个资源变量每时每刻至多被一个线程占用。
单例模式可以分为懒汉式和饿汉式,两者之间的区别在于创建实例的时间不同。懒汉式只有使用时才会创建实例,这种情况要考虑线程安全;饿汉式初始化就会创建实例,需要时直接调用,不用考虑安全问题。
饿汉式实现:
头文件:
// 饿汉实现 /
class Singleton
{
public:
// 获取单实例
static Singleton* GetInstance();
// 释放单实例,进程退出时调用
static void deleteInstance();
// 打印实例地址
void Print();
private:
// 将其构造和析构成为私有的, 禁止外部构造和析构
Singleton();
~Singleton();
// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
Singleton(const Singleton &signal);
const Singleton &operator=(const Singleton &signal);
private:
// 唯一单实例对象指针
static Singleton *g_pSingleton;
};
源文件:
// 代码一运行就初始化创建实例 ,本身就线程安全
Singleton* Singleton::g_pSingleton = new (std::nothrow) Singleton();
Singleton* Singleton::GetInstance()
{
return g_pSingleton;
}
void Singleton::deleteInstance()
{
if (g_pSingleton)
{
delete g_pSingleton;
g_pSingleton = nullptr;
}
}
void Singleton::Print()
{
std::cout << "我的实例内存地址是:" << this << std::endl;
}
Singleton::Singleton()
{
std::cout << "构造函数" << std::endl;
}
Singleton::~Singleton()
{
std::cout << "析构函数" << std::endl;
}
main程序:
#include <iostream>
#include <memory>
#include <mutex>
class Singleton {
public:
static std::shared_ptr<Singleton> getSingleton();
void print() {
std::cout << "Hello World." << std::endl;
}
~Singleton() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
private:
Singleton() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
static std::shared_ptr<Singleton> singleton = nullptr;
static std::once_flag singletonFlag;
std::shared_ptr<Singleton> Singleton::getSingleton() {
std::call_once(singletonFlag, [&] {
singleton = std::shared_ptr<Singleton>(new Singleton());
});
return singleton;
}
以上。