C++设计模式:简单工厂模式与工厂模式

#C++设计模式:简单工厂模式与工厂模式

在软件开发中,**设计模式**是一套可重用的、最佳的实践方案,用于解决开发过程中经常遇到的设计问题。本文将介绍两种常用的设计模式:**简单工厂模式**和**工厂模式**,并分析它们的优缺点和适用场景。

1. 设计模式的三大基本原则

在开始讨论代码实现之前,首先介绍设计模式的三大基本原则:

1.1- 开闭原则(Open-Closed Principle):软件实体应对扩展开放、对修改关闭。即在不修改现有代码的基础上,通过增加新代码来扩展功能。

1.2- 单一职责原则(Single Responsibility Principle):每个类应只有一个引起变化的原因,即一个类只负责一项职责。

1.3- 依赖倒置原则(Dependency Inversion Principle):高层模块不应该依赖低层模块,二者都应该依赖于抽象;抽象不应该依赖细节,细节应该依赖抽象。

2. 简单工厂模式

**简单工厂模式**是工厂模式的一种变体。它的特点是使用一个工厂类,根据不同的参数创建不同的实例。它**不符合开闭原则**,因为如果需要添加新的产品类型,必须修改工厂类的代码。

2.1 简单工厂模式的代码实现
// 抽象基类 AbtractSmile
class AbtractSmile {
public:
    virtual void transform() = 0; // 纯虚函数 //子类必须实现
    virtual void ability() = 0; // 纯虚函数
    virtual ~AbtractSmile() {} // 虚析构函数
};

// 派生类 SheepSmile
class SheepSmile : public AbtractSmile {
public:
    void transform() {
        cout << "sheep " << endl; 
    }
    void ability() {
        cout << "sheep ability" << endl; 
    }
};

// 派生类 BatSmile
class BatSmile : public AbtractSmile {
public:
    void transform() {
        cout << "bat " << endl; 
    }
    void ability() {
        cout << "bat ability" << endl; 
    }
};

// 枚举类型 MyType
enum MyType {
    Sheep,
    Bat,
    Lion
};

// 工厂类 MyFactory
class MyFactory {
public:
    AbtractSmile* createSmile(MyType type) {
        AbtractSmile* ptr = nullptr;
        switch (type) {
            case Sheep:
                ptr = new SheepSmile(); break; // 创建 SheepSmile 实例
            case Bat:
                ptr = new BatSmile(); break; // 创建 BatSmile 实例
            default:
                break;
        }
        return ptr;//返回父类指向子类的指针(多态)
    }
};

int main() {
    MyFactory* f = new MyFactory; // 创建工厂实例
    AbtractSmile* s = f->createSmile(Bat); // 创建 BatSmile 实例,用父类对象指向子类,实现多态
    s->transform(); // 调用对应子类 transform 函数
    s->ability(); // 调用对应子类 ability 函数
    return 0;
}
2.2 简单工厂模式的优缺点

- **优点**:实现简单,适用于产品种类固定的情况。
- **缺点**:不符合开闭原则。每次增加新产品时,都要修改 `MyFactory` 中的代码。

3. 工厂模式

工厂模式**是对简单工厂模式的进一步抽象。它将创建对象的逻辑进一步封装到独立的工厂类中,使得每个具体工厂类负责创建一种产品。这样做符合开闭原则和依赖倒置原则。

3.1 工厂模式的代码实现
class AbtractSmile //抽象类-父类
{
public:
    virtual void transform() = 0;
    virtual void ability() = 0;
    virtual ~AbtractSmile() {} //实现多态时,需加入虚析构函数,子类就能完整析构
};

class SheepSmile : public AbtractSmile //子类
{
public:
    void transform()
    {
        cout << "sheep " << endl;
    }
    void ability()
    {
        cout << "sheep ability" << endl;
    }
};
class BatSmile : public AbtractSmile //子类
{
public:
    void transform()
    {
        cout << "bat " << endl;
    }
    void ability()
    {
        cout << "bat ability" << endl;
    }
};

class AbtractFactory //工厂 抽象类-父类
{
public:
	virtual AbtractSmile* createSmile() = 0; 
    virtual ~AbtractFactory(){}  //实现多态时,需加入虚析构函数,子类就能完整析构
};

class SheepFactory : public AbtractFactory//子类工厂
{
public:
    AbtractSmile* createSmile() override //重写父类方法
    {
        return new SheepSmile(); //返回对应子类
    }
	~SheepFactory() //子类析构(多态)
    {
		cout << "SheepFactory 被析构..." << endl;
    }
};
class BatFactory : public AbtractFactory
{
public:
    AbtractSmile* createSmile() override
    {
        return new BatSmile();
    }
    ~BatFactory()
    {
        cout << "BatFactory 被析构..." << endl;
    }
};

int main()
{
    AbtractFactory* f = new SheepFactory();//使用父类工厂指向子类工厂
    AbtractSmile* obj = f->createSmile();//创建对应子类对象,并使用其父类指针指向
    obj->transform();//执行对应子类函数
    obj->ability();//执行对应子类函数
    delete obj;//触发析构
    delete f;//触发析构

    return 0;
}
3.2 工厂模式的优缺点

- **优点**:符合开闭原则和依赖倒置原则,每个具体工厂类负责创建一个产品类型,可以轻松添加新的工厂类,不需要修改现有代码。
- **缺点**:需要为每种产品创建一个具体工厂类,增加了代码量。

4.简单工厂模式和工厂模式的UML图

4.1简单工厂模式:

4.2工厂模式:

5. 总结

- **简单工厂模式**:适合产品种类较少的情况,但不符合开闭原则,扩展性较差。
- **工厂模式**:符合开闭原则和依赖倒置原则,更适合需要扩展产品类型的场景。

通过对比两种工厂模式,我们可以看到,**工厂模式**是一个更加灵活和可扩展的设计,符合设计模式的基本原则。

感谢b站up: 爱编程的大丙:https://space.bilibili.com/147020887

### 下载 Popper.min.js 文件的方法 对于希望获取 `popper.min.js` 的开发者来说,可以通过多种方式来实现这一目标。通常情况下,推荐通过官方渠道或可靠的分发网络 (CDN) 来获得最新的稳定版文件。 #### 使用 CDN 获取 Popper.min.js 最简单的方式之一是从流行的 CDN 中加载所需的 JavaScript 库。这不仅简化了集成过程,还可能提高性能,因为许多用户已经缓存了来自这些服务提供商的内容。例如: ```html <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2/dist/umd/popper.min.js"></script> ``` 这种方式不需要手动下载文件到本地服务器;只需将上述 `<script>` 标签添加至 HTML 文档中的适当位置即可立即使用 Popper 功能[^1]。 #### 从 npm 或 yarn 安装 如果项目采用模块化构建工具链,则可以直接利用包管理器如 npm 或 Yarn 进行安装。命令如下所示: ```bash npm install @popperjs/core # 或者 yarn add @popperjs/core ``` 之后可以根据具体需求引入特定功能模块,而不是整个库,从而减少打包后的体积并优化加载速度[^2]。 #### 访问 GitHub 发布页面下载压缩包 另一种方法是访问 Popper.js 的 [GitHub Releases](https://github.com/popperjs/popper-core/releases) 页面,在这里可以选择不同版本的 tarball 或 zip 归档进行下载解压操作。这种方法适合那些偏好离线工作环境或是想要定制编译选项的人群[^3]。 #### 手动克隆仓库 最后一种较为少见但也可行的办法便是直接克隆完整的 Git 存储库副本。这样可以获得开发分支以及历史记录等更多信息,适用于贡献代码或者深入学习内部机制的情况。 ```bash git clone https://github.com/popperjs/popper-core.git cd popper-core ``` 完成以上任一途径后便能成功取得所需版本的 Popper.min.js 文件,并将其应用于个人项目之中[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值