上一篇总结了设计模式七大原则, 接下来总结一下设计模式的几种创建型模式。
1. 单例模式
单例模式是一种创建型设计模式,其目的是确保类只有一个实例,并提供全局访问点。这意味着无论在应用程序的任何地方调用单例类的实例,都将返回同一个实例。单例模式通常在需要严格控制资源访问或确保全局状态的情况下使用。
在 C++ 中,可以通过多种方式实现单例模式,下面是一个基于懒汉式实现的简单示例:
#include <iostream>
class Singleton {
private:
// 私有的构造函数,防止外部代码直接实例化
Singleton() {}
// 静态私有成员变量,用于保存唯一的实例
static Singleton* instance;
public:
// 公有静态方法,用于获取单例实例
static Singleton* getInstance() {
// 懒汉式:在第一次调用时创建实例
if (!instance) {
instance = new Singleton();
}
return instance;
}
// 示例方法
void someMethod() {
std::cout << "Hello from Singleton!\n";
}
};
// 静态成员变量需要在类外进行初始化
Singleton* Singleton::instance = nullptr;
int main() {
// 获取单例实例
Singleton* singleton1 = Singleton::getInstance();
Singleton* singleton2 = Singleton::getInstance();
// 打印地址以验证是同一个实例
std::cout << "Address of singleton1: " << singleton1 << std::endl;
std::cout << "Address of singleton2: " << singleton2 << std::endl;
// 调用示例方法
singleton1->someMethod();
singleton2->someMethod();
return 0;
}
在这个示例中,Singleton
类的构造函数被声明为私有的,这样就无法直接在外部实例化该类。通过静态成员变量 instance
来保存唯一的实例,并在 getInstance()
方法中实现懒汉式的实例化,确保在第一次调用时创建实例。同时,通过静态方法 getInstance()
来获取该实例。
在 main()
函数中,我们获取两次单例实例,并打印它们的地址,验证它们是同一个实例。最后,通过调用示例方法 someMethod()
来验证单例的正确性。
2. 工厂模式
工厂模式是一种创建型设计模式,用于创建对象而无需指定具体的类。它通过将实际的对象创建过程封装在一个工厂类中,使得客户端代码不需要知道实际创建的对象是什么,从而实现了解耦。
工厂模式通常分为三种类型:简单工厂模式、工厂方法模式和抽象工厂模式。
1. 简单工厂模式(Simple Factory Pattern)
简单工厂模式是最基本的工厂模式,它包含一个工厂类和多个产品类。工厂类根据不同的参数来创建不同的产品对象。
#include <iostream>
// 抽象产品类
class Product {
public:
virtual void operation() = 0;
virtual ~Product() {}
};
// 具体产品类 A
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "Product A operation\n";
}
};
// 具体产品类 B
class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "Product B operation\n";
}
};
// 简单工厂类
class SimpleFactory {
public:
// 静态方法,根据参数创建不同的产品
static Product* createProduct(char type) {
if (type == 'A') {
return new ConcreteProductA();
} else if (type == 'B') {
return new ConcreteProductB();
}
return nullptr;
}
};
int main() {
// 使用简单工厂创建产品对象
Product* productA = SimpleFactory::createProduct('A');
Product* productB = SimpleFactory::createProduct('B');
// 调用产品对象的操作方法
if (productA) productA->operation();
if (productB) productB->operation();
delete productA;
delete productB;
return 0;
}
2. 工厂方法模式(Factory Method Pattern)
工厂方法模式定义了一个用于创建对象的接口,但将实际的创建工作推迟到子类中。这样可以使得一个类的实例化延迟到其子类。
#include <iostream>
// 抽象产品类
class Product {
public:
virtual void operation() = 0;
virtual ~Product() {}
};
// 具体产品类 A
class ConcreteProductA : public Product {
public:
void operation() override {
std::cout << "Product A operation\n";
}
};
// 具体产品类 B
class ConcreteProductB : public Product {
public:
void operation() override {
std::cout << "Product B operation\n";
}
};
// 抽象工厂类
class Factory {
public:
virtual Product* createProduct() = 0;
virtual ~Factory() {}
};
// 具体工厂类 A
class ConcreteFactoryA : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductA();
}
};
// 具体工厂类 B
class ConcreteFactoryB : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductB();
}
};
int main() {
// 使用工厂方法创建产品对象
Factory* factoryA = new ConcreteFactoryA();
Factory* factoryB = new ConcreteFactoryB();
Product* productA = factoryA->createProduct();
Product* productB = factoryB->createProduct();
// 调用产品对象的操作方法
if (productA) productA->operation();
if (productB) productB->operation();
delete factoryA;
delete factoryB;
delete productA;
delete productB;
return 0;
}
3. 抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体的类。它是一种工厂方法的泛化,一般由多个工厂方法组成。
#include <iostream>
// 抽象产品类 A
class AbstractProductA {
public:
virtual void operationA() = 0;
virtual ~AbstractProductA() {}
};
// 具体产品类 A1
class ConcreteProductA1 : public AbstractProductA {
public:
void operationA() override {
std::cout << "Product A1 operation\n";
}
};
// 具体产品类 A2
class ConcreteProductA2 : public AbstractProductA {
public:
void operationA() override {
std::cout << "Product A2 operation\n";
}
};
// 抽象产品类 B
class AbstractProductB {
public:
virtual void operationB() = 0;
virtual ~AbstractProductB() {}
};
// 具体产品类 B1
class ConcreteProductB1 : public AbstractProductB {
public:
void operationB() override {
std::cout << "Product B1 operation\n";
}
};
// 具体产品类 B2
class ConcreteProductB2 : public AbstractProductB {
public:
void operationB() override {
std::cout << "Product B2 operation\n";
}
};
// 抽象工厂类
class AbstractFactory {
public:
virtual AbstractProductA* createProductA() = 0;
virtual AbstractProductB* createProductB() = 0;
virtual ~AbstractFactory() {}
};
// 具体工厂类 1
class ConcreteFactory1 : public AbstractFactory {
public:
AbstractProductA* createProductA() override {
return new ConcreteProductA1();
}
AbstractProductB* createProductB() override {
return new ConcreteProductB1();
}
};
// 具体工厂类 2
class ConcreteFactory2 : public AbstractFactory {
public:
AbstractProductA* createProductA() override {
return new ConcreteProductA2();
}
AbstractProductB* createProductB() override {
return new ConcreteProductB2();
}
};
int main() {
// 使用抽象工厂创建产品对象
AbstractFactory* factory1 = new ConcreteFactory1();
AbstractFactory* factory2 = new ConcreteFactory2();
AbstractProductA* productA1 = factory1->createProductA();
AbstractProductB* productB1 = factory1->createProductB();
AbstractProductA* productA2 = factory2->createProductA();
AbstractProductB* productB2 = factory2->createProductB();
// 调用产品对象的操作方法
if (productA1) productA1->operationA();
if (productB1) productB1->operationB();
if (productA2) productA2->operationA();
if (productB2) productB2->operationB();
delete factory1;
delete factory2;
delete productA1;
delete productB1;
delete productA2;
delete productB2;
return 0;
}
3. 原型模式
原型模式是一种创建型设计模式,它允许对象在创建时通过复制一个现有对象的实例来进行创建,而不是通过构造函数。这样做可以减少创建对象所需的开销,特别是在对象的创建过程中需要进行复杂的初始化操作时。
在原型模式中,存在一个原型对象(Prototype),它是被复制的对象。新对象的创建过程是通过复制原型对象来完成的。
下面是一个简单的 C++ 示例,演示了如何使用原型模式:
#include <iostream>
#include <string>
// 原型基类
class Prototype {
public:
virtual Prototype* clone() const = 0; // 克隆方法
virtual void print() const = 0; // 打印方法
virtual ~Prototype() {} // 虚析构函数
};
// 具体原型类 A
class ConcretePrototypeA : public Prototype {
private:
std::string data_;
public:
ConcretePrototypeA(const std::string& data) : data_(data) {}
// 克隆方法的实现
Prototype* clone() const override {
return new ConcretePrototypeA(*this);
}
// 打印方法的实现
void print() const override {
std::cout << "ConcretePrototypeA: " << data_ << std::endl;
}
};
int main() {
// 创建原型对象
Prototype* prototypeA = new ConcretePrototypeA("Prototype Data");
// 克隆原型对象
Prototype* cloneA = prototypeA->clone();
// 打印原型对象和克隆对象
prototypeA->print();
cloneA->print();
// 释放资源
delete prototypeA;
delete cloneA;
return 0;
}
在上面的示例中,Prototype
类是原型的抽象基类,其中定义了纯虚函数 clone()
和 print()
。ConcretePrototypeA
类是具体的原型类,实现了基类中的虚函数。
在 main()
函数中,我们创建了一个具体原型对象 prototypeA
,然后通过调用其 clone()
方法来创建一个克隆对象 cloneA
。最后,我们调用原型对象和克隆对象的 print()
方法来验证它们的内容。
原型模式的优点是在于可以动态地创建对象,避免了耦合,提高了系统的灵活性。同时,它也可以避免直接调用构造函数,提高了性能。然而,原型模式的缺点是在实现深复制时可能会比较复杂,需要注意对象的所有成员的复制。
4. 建造者模式
建造者模式是一种创建型设计模式,旨在将复杂对象的构建过程与其表示分离,以便于相同的构建过程可以创建不同的表示形式。
在建造者模式中,有一个指挥者(Director)负责控制构建过程,以及一个具体的建造者(Builder)接口和具体的建造者类,负责实际构建对象的各个部分。最终,通过指挥者来指导具体的建造者构建对象。
下面是一个简单的 C++ 示例,演示了如何使用建造者模式:
#include <iostream>
#include <string>
// 产品类
class Product {
private:
std::string partA_;
std::string partB_;
std::string partC_;
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() const {
std::cout << "PartA: " << partA_ << std::endl;
std::cout << "PartB: " << partB_ << std::endl;
std::cout << "PartC: " << partC_ << std::endl;
}
};
// 抽象建造者类
class Builder {
public:
virtual void buildPartA() = 0;
virtual void buildPartB() = 0;
virtual void buildPartC() = 0;
virtual Product* getProduct() = 0;
virtual ~Builder() {}
};
// 具体建造者类
class ConcreteBuilder : public Builder {
private:
Product* product_;
public:
ConcreteBuilder() {
product_ = new Product();
}
void buildPartA() override {
product_->setPartA("PartA");
}
void buildPartB() override {
product_->setPartB("PartB");
}
void buildPartC() override {
product_->setPartC("PartC");
}
Product* getProduct() override {
return product_;
}
~ConcreteBuilder() {
delete product_;
}
};
// 指挥者类
class Director {
public:
Product* construct(Builder* builder) {
builder->buildPartA();
builder->buildPartB();
builder->buildPartC();
return builder->getProduct();
}
};
int main() {
Director director;
ConcreteBuilder builder;
Product* product = director.construct(&builder);
product->show();
delete product;
return 0;
}
在这个示例中,我们首先定义了产品类 Product
,它包含了需要构建的各个部分。然后,定义了抽象建造者类 Builder
,其中包含了构建各个部分的纯虚函数。接着,具体建造者类 ConcreteBuilder
继承自抽象建造者类,并实现了具体的构建过程。最后,指挥者类 Director
控制了构建过程,并返回最终构建的产品对象。
在 main()
函数中,我们创建了一个指挥者对象 director
和一个具体建造者对象 builder
,然后通过指挥者来构建产品对象,并最终展示该产品的各个部分。
建造者模式的优点在于可以将构建过程与表示分离,从而可以更灵活地控制对象的构建。同时,由于具体的构建过程都在具体的建造者类中实现,因此可以方便地扩展和修改构建过程。然而,建造者模式的缺点在于需要编写更多的类,增加了系统的复杂性。