设计模式之禅1-5

单例模式

单例模式要求确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例(Ensure a class has only one instance, and provide a global point of access to it)

单例模式优点:
1.资源控制,确保全局只有一个实例对象,避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在 内存中,避免对同一个资源文件的同时写操作

2.能够进行全局状态管理,单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单 例类,负责所有数据表的映射处理

3.性能优化,能够减少对象创建开销,特别是一个对象需要频繁地 创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显

单例模式缺点:
1.违反单一职责原则,常常会职责过多,比如一个单例可以log,loadConfig等
2.测试困难,因为是单例在启动之前就初始化,所以一般使用初始化列表,所以很难使用依赖注入的方法,所以造成紧密耦合的依赖,比如使用的成员是实现类而不是抽象类(违反了依赖倒置的原则)
3.继承和扩展的局限性,无法通过继承创建多个实例

在设计模式中,接口通常通过纯虚类(abstract class)在C++中实现。接口定义了一组方法,但不涉及具体实现,单例模式通常不使用接口,原因如下:
自我实例化:单例类需要控制其实例化过程,确保只有一个实例。这通常通过私有构造函数和静态访问方法实现。如果引入接口,使用接口的代码需要通过接口指针或引用访问,这会破坏单例的全局访问点特性。
接口无意义:接口本身是抽象的,不能实例化。单例需要一个具体的类来管理唯一实例,接口无法直接支持这种需求。

由于单例类通常没有接口,扩展其功能较为困难。在需要扩展单例功能时,主要有以下几种方式:
修改现有代码:直接在单例类中添加新功能,需要修改类定义,影响所有使用该类的地方。
继承单例类(不推荐):虽然技术上可以通过继承扩展单例,但这会导致多个实例或破坏单例特性,通常不推荐。

工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类(Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.)

工厂方法模式是一种创建型设计模式,旨在提供一个用于创建对象的接口,而不暴露对象创建的具体逻辑。该模式通过将对象的实例化推迟到子类,使得系统能够在不修改现有代码的情况下增加新的产品

目的
封装对象创建:将对象创建过程封装在工厂类中,隐藏了具体实现细节。
提高灵活性:通过继承和多态,允许在不修改客户端代码的情况下扩展新产品。
降低耦合:客户端不再依赖具体类,只依赖抽象类型,提高了代码的灵活性和可维护性。

优点
单一职责:对象创建的职责由工厂类单独承担,符合单一职责原则。
符合开闭原则:对扩展开放,对修改封闭。增加新产品无需修改现有工厂类,只需新增具体工厂和产品类。
降低耦合:客户端与具体产品类解耦,依赖于抽象工厂和产品接口。

缺点
类的数量增加:每增加一种产品都需要相应的具体工厂类,可能导致系统中类的数量增多,增加复杂度。
使用复杂性:与简单的直接实例化相比,工厂方法的结构更复杂,适用于较为复杂的对象创建情境。

简单工厂模式
简单工厂模式并非标准的设计模式,但常被用来快速创建对象,它通过一个工厂类,根据传入的参数创建不同的产品实例

class SimpleButtonFactory{
public:
    enum class ButtonType{Windows,Mac};

    static std::unique_ptr<Button> createButton(ButtonType type){
    switch(type){
        case ButtonType::Windows:
        return std::make_unique<WindowsButton>();
        case ButtonType::Max:
        return std::make_unique<MaxButton>();
        default:
        return nullptr;
    }
    }
};

抽象工厂模式
抽象工厂模式旨在创建一系列相关或相互依赖的对象,而不仅仅是一个产品,它提供一个接口,用于创建一组相关或依赖的对象,而无需指定具体类

class TextBox{
public:
    virtual ~TextBox(){}
    virtual std::string paint() const = 0;
};

class WindowsTextBox : public TextBox{
public:
    std::string paint() const override {
        return "Render a text box in a Windows style.";
    }
}
class MacTextBox : public TextBox {
public:
    std::string paint() const override {
        return "Render a text box in a macOS style.";
    }
};
class GUIFactory{
public:
    virtual ~GUIFactory(){}
    virtual std::unique_ptr<TextBox> createTextBox() const = 0;
};

class WindowsGUIFactory : public GUIFactory {
public:
    std::unique_ptr<TextBox> createTextBox() const override {
        return std::make_unique<WindowsTextBox>();
    }
};

class MacGUIFactory : public GUIFactory {
public:
    std::unique_ptr<TextBox> createTextBox() const override {
        return std::make_unique<MacTextBox>();
    }
};

建造者模式

建造者模式是一种创建型设计模式,旨在分步骤构建复杂对象,使得同一构建过程可以创建不同的表示。建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

具体来说,建造者模式通过将一个复杂对象的构建分解成多个简单的步骤,并允许通过不同的步骤创建不同的对象。模式中的主要角色:
1.Builder(抽象建造者):定义创建产品的各个部件的抽象方法
2.ConcreteBuilder(具体建造者):实现Builder接口,实现各个组件的具体构建,并提供获取最终产品的方法
3.Director(指挥者):负责安排建造者按照特定的顺序来构建产品
4.Product(产品):表示被构建的复杂对象,包含多个部件


class Car {
public:
    void setEngine(const std::string& engine) {
        this->engine = engine;
    }

    void setWheels(const std::string& wheels) {
        this->wheels = wheels;
    }

    void setColor(const std::string& color) {
        this->color = color;
    }

private:
    std::string engine;
    std::string wheels;
    std::string color;
};

class CarBuilder {
public:
    virtual ~CarBuilder() = default;

    virtual void buildEngine() = 0;

    virtual void buildWheels() = 0;

    virtual void buildColor() = 0;

    std::unique_ptr<Car> getCar() {
        return std::move(car);
    }
protected:
    std::unique_ptr<Car> car = std::make_unique<Car>();
};

class SportsCarBuilder :public CarBuilder {
public:
    void buildEngine() override {
        car->setEngine("V8 Engine");
    }

    void buildWheels() override {
        car->setWheels("20-inch Alloy Wheels");
    }

    void buildColor() override {
        car->setColor("Red");
    }
};

class SUVCarBuilder : public CarBuilder {
public:
    void buildEngine() override {
        car->setEngine("V6 Engine");
    }

    void buildWheels() override {
        car->setWheels("18-inch Steel Wheels");
    }

    void buildColor() override {
        car->setColor("Black");
    }
};

class CarDirecotr {
public:
    void setBuilder(std::unique_ptr<CarBuilder> builder) {
        builder = std::move(builder);
    }

    std::unique_ptr<Car> constructCar() {
        if (builder) {
            builder->buildEngine();
            builder->buildWheels();
            builder->buildColor();
            return builder->getCar();
        }
        return nullptr;
    }
private:
    std::unique_ptr<CarBuilder> builder;
};

int main() {
    CarDirector director;

    // 构建一辆跑车
    std::unique_ptr<CarBuilder> sportsCarBuilder = std::make_unique<SportsCarBuilder>();
    director.setBuilder(std::move(sportsCarBuilder));
    std::unique_ptr<Car> sportsCar = director.constructCar();
    std::cout << "Sports Car:" << std::endl;
    sportsCar->showSpecifications();
    std::cout << std::endl;

    // 构建一辆SUV
    std::unique_ptr<CarBuilder> suvCarBuilder = std::make_unique<SUVCarBuilder>();
    director.setBuilder(std::move(suvCarBuilder));
    std::unique_ptr<Car> suvCar = director.constructCar();
    std::cout << "SUV Car:" << std::endl;
    suvCar->showSpecifications();

    return 0;
}