01-创建型设计模式(共6种)

        在面向对象软件设计中,基于创建的设计模式是处理对象创建机制的模式。这些模式旨在根据实际情况创建对象,提高代码的灵活性和可重用性。其主要目标是控制对象的创建过程,尤其是当使用构造函数直接创建对象的方式效率不高或不够充分时。

1. Simple Factory(简单工厂模式)

        简单工厂模式是一种创建型设计模式,它通过一个简单的工厂类来实例化对象,而不需要直接在客户端代码中实例化对象

        这种模式将对象的创建过程封装在工厂类中,客户端只需调用工厂类的方法即可获得所需的对象实例

        以下是模式示例:

#include <iostream>
#include <string>

// 抽象产品类
class Product {
public:
    virtual void use() = 0;
};

// 具体产品类A
class ConcreteProductA : public Product {
public:
    void use() override {
        std::cout << "Using Concrete Product A" << std::endl;
    }
};

// 具体产品类B
class ConcreteProductB : public Product {
public:
    void use() override {
        std::cout << "Using Concrete Product B" << std::endl;
    }
};

// 简单工厂类
class SimpleFactory {
public:
    // 根据传入的参数创建对应的产品实例
    static Product* createProduct(const std::string& type) {
        if (type == "A") {
            return new ConcreteProductA();
        } else if (type == "B") {
            return new ConcreteProductB();
        } else {
            return nullptr; // 可以根据需要进行异常处理或返回默认产品
        }
    }
};

int main() {
    // 使用简单工厂创建产品实例
    Product* productA = SimpleFactory::createProduct("A");
    Product* productB = SimpleFactory::createProduct("B");

    // 使用产品
    if (productA) {
        productA->use();
        delete productA;
    }
    if (productB) {
        productB->use();
        delete productB;
    }

    return 0;
}

2. Factory Method(工厂模式)

        工厂方法是一种创建设计模式,即与对象创建有关。 在工厂模式中,我们在不向客户端公开创建逻辑的情况下创建对象,并且客户端使用相同的通用接口来创建新类型的对象。 

        在C++中,Factory Method模式通常通过一个抽象基类具体子类来实现
        这种设计模式的好处在于,客户端代码只需要知道要创建的产品的接口对应的工厂类即可,而无需了解具体的产品创建细节这样可以降低代码的耦合度,提高代码的可维护性和扩展性

        以下是模式示例:

#include <iostream>
#include <memory>

// 抽象产品类
class Product {
public:
    virtual void use() = 0;
    virtual ~Product() = default;
};

// 具体产品类A
class ConcreteProductA : public Product {
public:
    void use() override {
        std::cout << "Using Concrete Product A" << std::endl;
    }
};

// 具体产品类B
class ConcreteProductB : public Product {
public:
    void use() override {
        std::cout << "Using Concrete Product B" << std::endl;
    }
};

// 工厂接口
class Factory {
public:
    virtual std::shared_ptr<Product> createProduct() = 0;
    virtual ~Factory() = default;
};

// 具体工厂类A
class ConcreteFactoryA : public Factory {
public:
    std::shared_ptr<Product> createProduct() override {
        return std::make_shared<ConcreteProductA>();
    }
};

// 具体工厂类B
class ConcreteFactoryB : public Factory {
public:
    std::shared_ptr<Product> createProduct() override {
        return std::make_shared<ConcreteProductB>();
    }
};

int main() {
    // 使用工厂A创建产品A
    std::shared_ptr<Factory> factoryA = std::make_shared<ConcreteFactoryA>();
    std::shared_ptr<Product> productA = factoryA->createProduct();
    productA->use();

    // 使用工厂B创建产品B
    std::shared_ptr<Factory> factoryB = std::make_shared<ConcreteFactoryB>();
    std::shared_ptr<Product> productB = factoryB->createProduct();
    productB->use();

    return 0;
}

3. Abstract Factory(抽象工厂模式)

     抽象工厂模式是一种创建型设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式通过引入抽象工厂接口和具体工厂实现类来实现对象的创建,可以实现对象的簇间的解耦,同时也支持易于替换整个工厂簇的操作。

        在 C++ 中,抽象工厂模式通常涉及以下几个角色:

        ①. Abstract Factory(抽象工厂接口):定义了创建一系列相关对象的方法,通常包含多个工厂方法。

        ②. Concrete Factory(具体工厂实现类):实现了抽象工厂接口,负责创建一系列相关的对象。

        ③. Abstract Product(抽象产品接口):定义了一类产品对象的接口。

        ④. Concrete Product(具体产品类):实现了抽象产品接口,是具体工厂创建的产品对象。

4. Singleton(单例模式)

        意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

        这种模式通常用于需要在整个应用程序中共享一个资源控制特定资源访问的情况下。

        在C++中,单例模式可以通过私有化构造函数、提供一个静态方法或静态变量来实现

        双重锁(Double-Checked Locking)单例模式是单例模式的一种改进,旨在在多线程环境下提供更高效的单例实现。它通过双重检查来确保只有在实例尚未创建时才会加锁创建新实例,从而避免了每次获取实例都加锁的性能开销

        在C++中,双重锁单例模式通常结合使用互斥锁(mutex)和原子操作来实现。

         以下是模式示例:

#include <iostream>
#include <memory>
#include <mutex>

class Singleton {
private:
    static std::shared_ptr<Singleton> instance;
    static std::mutex mutex;
    Singleton() {} // 私有化构造函数

public:
    static std::shared_ptr<Singleton> getInstance() {
        // 第一次检查,提高效率
        if (!instance) {
            std::lock_guard<std::mutex> lock(mutex); // 加锁
            // 第二次检查,避免多线程竞争时重复创建实例
            if (!instance) {
                instance = std::shared_ptr<Singleton>(new Singleton());
            }
        }
        return instance;
    }

    void showMessage() {
        std::cout << "Hello from Singleton!" << std::endl;
    }
    
    /**
     * 如果instance不是智能指针,需要用单独的deinit来销毁实例
     */
    // void deinit() {
    //     if (instance) {
    //         delete instance;
    //         instance = nullptr;
    //     }
    // }
};

std::shared_ptr<Singleton> Singleton::instance = nullptr;
std::mutex Singleton::mutex;

int main() {
    std::shared_ptr<Singleton> singleton1 = Singleton::getInstance();
    singleton1->showMessage();

    std::shared_ptr<Singleton> singleton2 = Singleton::getInstance();
    singleton2->showMessage();

    // 输出true,说明singleton1和singleton2是同一个实例
    std::cout << (singleton1 == singleton2) << std::endl;

    return 0;
}

4.1 单例模式中的static变量说明

        在C++中,若使用-std=c++11及以上编译器,则上述示例对多线程的同步操作,也是适用的。

但是什么时候去销毁? (好像不太好销毁,因此还是推荐使用双重锁机制来创建单例)

[Declaration statement]
    Dynamic initialization of a block-scope variable with static storage duration or thread storage duration is performed the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration.
    If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. Thus,the singleton pattern for C++11, double-checked locking is not needed.


    A conforming implementation cannot introduce any deadlock around execution of the initializer. Deadlocks can still be caused by the program logic; the implementation need only avoid deadlocks due to its own synchronization operations. 


[Static local variables]

    If multiple threads attempt to initialize the same static local variable concurrently, the initialization occurs exactly once (similar behavior can be obtained for arbitrary functions with std::call_once).
    Note: usual implementations of this feature use variants of the double-checked locking pattern, which reduces runtime overhead for already-initialized local statics to a single non-atomic boolean comparison.

        但对于类似Java语言来说,多线程同时操作时,用DCL方法来创建单一实例。

// Double Checked Locking based Java implementation of
// singleton design pattern
class Singleton
{
	private static volatile Singleton obj = null;

	private Singleton() {}

	public static Singleton getInstance() {
		if (obj == null) {
			// To make thread safe
			synchronized (Singleton.class) {
				// check again as multiple threads
				// can reach above step
				if (obj==null) obj = new Singleton();
			}
		}

		return obj;
	}
}

5. Builder(建造者模式)

        建造者模式(Builder Pattern)是一种创建型设计模式,它允许你创建一个复杂对象的过程与其表示分离,从而使同样的创建过程可以产生不同的表示。这种模式常用于创建包含多个组件或部分的复杂对象。

        在C++中,建造者模式通常由一个Builder接口具体的Builder实现类来实现,以及一个Director类来指导建造过程。

        以下是模式示例:

#include <iostream>
#include <string>
#include <memory>

// 产品类
class Pizza {
public:
    void setDough(const std::string& dough) {
        dough_ = dough;
    }

    void setTopping(const std::string& topping) {
        topping_ = topping;
    }

    void setSauce(const std::string& sauce) {
        sauce_ = sauce;
    }

    void showPizza() {
        std::cout << "Pizza with " << dough_ << " dough, " << topping_ << " topping, and " << sauce_ << " sauce" << std::endl;
    }

private:
    std::string dough_;     // 面团
    std::string topping_;   // 配料
    std::string sauce_;     // 酱汁
};

// 建造者接口
class PizzaBuilder {
public:
    virtual void buildDough() = 0;
    virtual void buildTopping() = 0;
    virtual void buildSauce() = 0;
    virtual std::shared_ptr<Pizza> getPizza() = 0;
    virtual ~PizzaBuilder() = default;
};

// 具体建造者类(玛格丽塔披萨)
class MargheritaPizzaBuilder : public PizzaBuilder {
public:
    void buildDough() override {
        pizza_->setDough("thin crust");
    }

    void buildTopping() override {
        pizza_->setTopping("mozzarella cheese");
    }

    void buildSauce() override {
        pizza_->setSauce("tomato sauce");
    }

    std::shared_ptr<Pizza> getPizza() override {
        return pizza_;
    }

private:
    std::shared_ptr<Pizza> pizza_ = std::make_shared<Pizza>();
};

// 指导者类
class PizzaDirector {
public:
    // 同样的创建过程,因PizzaBuilder抽象类生产不同的产品表示;
    void makePizza(PizzaBuilder& builder) {
        builder.buildDough();
        builder.buildTopping();
        builder.buildSauce();
    }
};

int main() {
    PizzaDirector director;
    MargheritaPizzaBuilder margheritaBuilder;
    
    director.makePizza(margheritaBuilder);
    std::shared_ptr<Pizza> pizza = margheritaBuilder.getPizza();
    pizza->showPizza();

    return 0;
}

6. Prototype(原型模式)

        原型模式是一种创建型设计模式,它允许你通过复制现有对象来创建新对象,而无需知道对象的具体类。这种模式通过克隆现有对象来创建新对象,可以提高对象创建的效率,并且可以避免因为创建过程复杂或耗时而造成的性能损失。

        在C++中,原型模式通常通过一个抽象基类具体子类来实现,同时使用原型管理类来管理原型对象

        以下是模式示例:

#include <iostream>
#include <memory>

// 抽象原型类
class Prototype {
public:
    virtual std::shared_ptr<Prototype> clone() = 0;
    virtual void showInfo() = 0;
    virtual ~Prototype() = default;
};

// 具体原型类A
class ConcretePrototypeA : public Prototype {
public:
    std::shared_ptr<Prototype> clone() override {
        return std::make_shared<ConcretePrototypeA>(*this);
    }

    void showInfo() override {
        std::cout << "ConcretePrototypeA" << std::endl;
    }
};

// 具体原型类B
class ConcretePrototypeB : public Prototype {
public:
    std::shared_ptr<Prototype> clone() override {
        return std::make_shared<ConcretePrototypeB>(*this);
    }

    void showInfo() override {
        std::cout << "ConcretePrototypeB" << std::endl;
    }
};

// 原型管理类
class PrototypeManager {
public:
    void addPrototype(const std::string& key, std::shared_ptr<Prototype> prototype) {
        prototypes_[key] = prototype;
    }

    std::shared_ptr<Prototype> getPrototype(const std::string& key) {
        if (prototypes_.find(key) != prototypes_.end()) {
            return prototypes_[key]->clone();
        } else {
            return nullptr;
        }
    }

private:
    std::unordered_map<std::string, std::shared_ptr<Prototype>> prototypes_;
};

int main() {
    PrototypeManager manager;
    manager.addPrototype("A", std::make_shared<ConcretePrototypeA>());
    manager.addPrototype("B", std::make_shared<ConcretePrototypeB>());

    std::shared_ptr<Prototype> cloneA = manager.getPrototype("A");
    std::shared_ptr<Prototype> cloneB = manager.getPrototype("B");

    if (cloneA) {
        cloneA->showInfo();
    }

    if (cloneB) {
        cloneB->showInfo();
    }

    return 0;
}

下一篇: 02-结构型设计模式(共7种)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值