【c++设计模式03】创建型1:简单工厂模式(Simple Factory Pattern)
- 一、工厂模式
- 二、简单工厂模式
- 三、UML类图
- 四、demo
- 五、使用多态的简单工厂模式
- 1、UML类图——使用多态
- 2、demo——使用多态
原创作者:郑同学的笔记
原创地址:https://zhengjunxue.blog.csdn.net/article/details/132282650
qq技术交流群:921273910
类型 | 序号 | 设计模式 | 描述 |
创建型 | 1 | 简单工厂模式 (Simple Factory Pattern) | 通过一个工厂类负责创建所有产品的实例 |
2 | 工厂方法模式 (Factory Pattern) | 将对象的实例化延迟到子类中实现 | |
3 | 抽象工厂模式 (Abstact Factory Pattern) | 通过提供一组相关产品的接口,实现了一系列具体工厂类来创建不同产品族的实例 | |
4 | 单例模式 (Singleton Pattern) | 保证一个类只有一个实例 | |
5 | 创建者模式 (Builder Pattern) | 如何创建一个组合对象 | |
6 | 原型模式 (Prototype Pattern) | 它通过复制已有对象来创建新的实例 |
一、工厂模式
-
工厂模式是一种软件设计模式,它提供了一种创建对象的方式,将对象的实例化和使用分离开来。工厂模式通过定义一个公共的接口或抽象类来创建对象,并由实现该接口或继承该抽象类的具体工厂类负责实例化对象。
-
在工厂模式中,客户端通过调用工厂类的方法来获取所需的对象,而无需直接实例化对象。工厂类根据不同的需求条件,使用不同的逻辑或算法创建相应的对象,隐藏了对象创建的具体细节。
-
工厂模式可以有效地降低系统的耦合度,提高代码的可维护性和可扩展性。它符合面向对象设计原则中的开放封闭原则,即对扩展开放,对修改封闭。当需要新增一种产品时,只需添加相应的具体产品类和对应的工厂类,而无需修改已有的代码。
-
常见的工厂模式包括简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂模式通过一个工厂类负责创建所有产品的实例;
工厂方法模式将对象的实例化延迟到子类中实现;
抽象工厂模式通过提供一组相关产品的接口,实现了一系列具体工厂类来创建不同产品族的实例。
二、简单工厂模式
基于简单工厂模式去创建对象的时候,需要提供一个工厂类,专门用于生产需要的对象,这样关于对象的创建操作就被剥离出去了。
简单工厂模式相关类的创建和使用步骤如下:
- 创建一个新的类, 可以将这个类称之为工厂类。对于简单工厂模式来说,需要的工厂类只有一个。
- 在这个工厂类中添加一个公共的成员函数,通过这个函数来创建我们需要的对象,关于这个函数一般将其称之为工厂函数。
- 关于使用,首先创建一个工厂类对象,然后通过这个对象调用工厂函数,这样就可以生产出一个指定类型的实例对象了。
三、UML类图
四、demo
#include<iostream>
using namespace std;class Apple {
public:void say(){cout << "i am a Apple\n";}
};
class Banana {
public:void say(){cout << "i am a Banana\n";}
};enum class Type :char {APPLE,BANAN
};
class SimpleFactory {
public:void* createFruit(Type type) {void* ptr = nullptr;switch (type){case Type::APPLE:ptr = new Apple();break;case Type::BANAN:ptr = new Banana();break;default:cout << "水果类型错误\n";break;}return ptr;}
};int main()
{SimpleFactory* factory = new SimpleFactory();Apple* apple1 =(Apple*)factory->createFruit(Type::BANAN);apple1->say();Banana* banana1 = (Banana*)factory->createFruit(Type::APPLE);banana1->say();return 0;
}
输出
- 关于水果的类型,上面的类中用到了强类型枚举(C++11新特性),增强了代码的可读性,并且将枚举元素设置为了char类型,节省了内存。
- 函数createFruit(Type type)的返回值是void*类型,这样处理主要是因为每个case 语句创建出的对象类型是不一样的,为了实现兼容,故此这样处理。
- 得到函数createFruit(Type type)的返回值之后,还需要将其转换成实际的类型,处理起来还是比较繁琐的。
五、使用多态的简单工厂模式
类和类之间有继承关系。
父类中有虚函数,并且在子类中需要重写这些虚函数。
使用父类指针或引用指向子类对象。
1、UML类图——使用多态
我们需要给苹果、香蕉提供一个基类,然后让上边的2个类Apple、Banana作为子类继承这个基类。根据分析我们就有画出简单工厂模式的UML类图了:
2、demo——使用多态
由于水果和苹果、香蕉有继承关系, 并且实现了多态,所以父类的析构函数也应该是虚函数,这样才能够通过父类指针或引用析构子类的对象。
#include<iostream>
using namespace std;class AbstractFruit {
public:virtual void say() {};virtual ~AbstractFruit() {};
};
class Apple: public AbstractFruit {
public:void say() override{cout << "i am a Apple\n";}
};
class Banana : public AbstractFruit {
public:void say(){cout << "i am a Banana\n";}
};enum class Type :char {APPLE,BANAN
};
class SimpleFactory {
public:AbstractFruit* createFruit(Type type) {AbstractFruit* ptr = nullptr;switch (type){case Type::APPLE:ptr = new Apple;break;case Type::BANAN:ptr = new Banana();break;default:cout << "水果类型错误\n";break;}return ptr;}
};int main()
{SimpleFactory* factory = new SimpleFactory();AbstractFruit* obj = factory->createFruit(Type::BANAN);obj->say();return 0;
}
工厂函数createFruit(Type type)的返回值修改成了AbstractFruit*类型,这是水果类的基类,通过这个指针保存的是子类对象的地址,这样就实现了多态,所以在main()函数中,通过obj对象调用的实际是子类say中的函数,因此打印出的信息应该是这样的:
输出