一、什么是简单工厂模式?
简单点说就是在一个静态的方法中,根据参数配置返回不同的对象。
在简单工厂模式中,我们用到了面向对象的一个很重要的设计原则:面向接口编程而不是面
向实现编程。用一个接口Bird抽象了鸟这一类产品的的行为。而我们的工厂返回的就是所有支持这些行为的产品。
使用者关注的是用这些产品(调用这些接口的方法),它不关注产品细节(怎么创建、实现怎样)
二、代码示例
没有使用简单工厂模式
我们先来看看不使用工厂的话,代码是怎么样的,首先定义产品。
ppp.cpp
/** * 鸟类的抽象 */ class Bird{ public: virtual void fly()= 0; // 因为是接口用重虚函数定义 virtual void quark()= 0; }; /** * 具体的鸟类 */ class Eaggle:public Bird{ public: virtual void fly(){ cout <<"eaggle is flying"<< endl; } virtual void quark(){ cout <<"eaggle is quark" << endl; } }; /** * 具体的鸟类 */ class Chicken:public Bird{ public: virtual void fly(){ cout <<"chicken is flying"<< endl; } virtual void quark(){ cout <<"chicken is quark" << endl; } };
产品的使用
int main() { Bird* chicken = new Chicken(); Bird* eaggle = new Eaggle(); }
显然,现在使用者是和各种鸟(产品)关联在了一起。假如将来有越来越多的鸟加入进来,那么所有使用者的代码都得跟着动。如果不支持某种鸟类也是同样的道理。
使用简单工厂模式
simplefactory.cpp
#ifndef __SIMPLEFACTORY_H__ #define __SIMPLEFACTORY_H__ #include <iostream> #include <string> using namespace std; enum{ EAGGLE, CHICKEN, PARROT }; /** * 1.鸟类的抽象 */ class Bird{ public: virtual void fly()= 0; // 因为是接口用重虚函数定义 virtual void quark()= 0; }; /** * 2.具体的鸟类 */ class Eaggle:public Bird{ public: virtual void fly(){ cout <<"eaggle is flying"<< endl; } virtual void quark(){ cout <<"eaggle is quark" << endl; } }; /** * 具体的鸟类 */ class Chicken:public Bird{ public: virtual void fly(){ cout <<"chicken is flying"<< endl; } virtual void quark(){ cout <<"chicken is quark" << endl; } }; /** * 3.简单工厂类,通过参数获得不同的对象 */ class SimpleFactory{ public: static Bird* createBird(int type){ switch(type){ case EAGGLE: return new Eaggle(); case CHICKEN: return new Chicken(); // 添加要创建的其他鸟类 (实际创建产品函数里面需要很多东西) } } };
1.首先把产品抽象抽出来,定义鸟类接口,它们有一个共同点就是可以飞或者叫 。由于fly() 是纯虚函数(
= 0
),Bird
不能直接实例化,必须由子类继承并实现。
2.在具体产品类里面实现fly的方法
3.把对象的创建抽出来,创在静态方法里面。假如fly() 的创建有什么变动,只需更改对应函数即可。使用的地方完成不动。如果有新的产品,直接添加即可。
main.cpp
#include "simplefactory.h" int main(int argc, char** argv) { Bird* chicken = SimpleFactory::createBird(CHICKEN); chicken->fly(); chicken->quark(); Bird* eaggle = SimpleFactory::createBird(EAGGLE); eaggle->fly(); eaggle->quark(); }
关键点1: 要有一个抽象产品类,用来表示产品的共同行为。
指针Bird只跟产品抽象接口打交道,没有针对具体的产品(老鹰、鸡)来写代码
关键点2: 使用者只依赖工厂类,而不依赖于各种各样的鸟类。各种具体的鸟的类名不见了,只跟SimpleFactory打交道
静态工厂的优点是使用很方便,使用者不需要知道产品的类名,通过参数就可以得到不同的产品。
静态工厂的缺点是所有产品的创建逻辑都在静态工厂中,会让静态工厂的逻辑变得很重,违反了单一职责原则。新增或删除产品时,都要到静态工厂中修改。
三、综合示例
#ifndef __SIMPLEFACTORY_H__ #define __SIMPLEFACTORY_H__ #include <iostream> #include <string> using namespace std; enum{ BENZ, BYD, BMW }; /** * 产品类的抽象 */ class ICar{ public: virtual void run() = 0; // 因为是接口用重虚函数定义 }; /** * 具体的产品类 */ class Benz:public ICar{ public: virtual void run() { cout << "Benz run" << endl; } }; /** * 具体的产品类 */ class Byd:public ICar{ public: virtual void run() { cout << "Byd run" << endl; } }; /** * 简单工厂类,通过参数获得不同的对象 */ class SimpleFactory{ public: static ICar* createCar(int type){ switch(type){ case BENZ: return new Benz(); case BYD: return new Byd(); // 添加要创建的产品 (实际创建产品函数里面需要很多东西) // ... default: return nullptr; // 或抛出异常 } } };
#include "simplefactory.h" // 使用这个工厂 int main(int argc, char** argv) { ICar* benz = SimpleFactory::createCar(BENZ); ICar* byd = SimpleFactory::createCar(BYD); benz->run(); // 输出 "Benz run" byd->run(); // 输出 "Byd run" delete benz; // 需要手动释放内存 delete byd; return 0; }
代码实现了一个 简单工厂模式,用于创建不同类型的汽车对象(
Benz
、Byd
)。它的核心思想是 将对象的创建逻辑封装在一个工厂类中,客户端只需要传入一个参数(如BENZ
或BYD)
,工厂就会返回对应的具体产品对象,而无需关心对象的创建细节。
注意事项:
由于返回的是
new
分配的指针,需要手动delete
释放内存(更好的方式是使用智能指针std::unique_ptr
)。使用智能指针避免内存泄漏
#include <memory> // 需要添加的头文件 static std::unique_ptr<ICar> createCar(int type) { switch(type) { case BENZ: return std::make_unique<Benz>(); case BYD: return std::make_unique<Byd>(); default: return nullptr; } }
使用
std::unique_ptr
自动管理内存,无需手动delete
。