工厂模式是一种创建型设计模式,用于创建对象而无需指定具体创建的类。它通过提供一个共同的接口来创建对象,但允许子类决定实例化哪个类。工厂模式的主要目的是将对象的创建和使用分离,以便代码更容易扩展和维护。
关键组成部分:
-
工厂接口(Factory Interface):
- 定义一个创建对象的接口,通常是一个抽象类或接口。工厂接口可能包含多个工厂方法,每个方法用于创建不同类型的对象。
-
具体工厂(Concrete Factory):
- 实现工厂接口,负责创建具体的产品对象。每个具体工厂类对应于创建一类具体产品。
-
产品接口(Product Interface):
- 定义工厂方法创建的对象的接口,通常是一个抽象类或接口。具体产品类实现这个接口。
-
具体产品(Concrete Product):
- 实现产品接口定义的具体对象。工厂方法将创建这些具体产品的实例。
工作原理:
工厂模式通过引入工厂类来代替在客户端代码中直接使用 new
关键字来创建对象。客户端代码通过调用工厂方法来创建所需的对象,而无需了解具体的对象类型。这种方式使得系统更具灵活性,因为可以随时更改或扩展创建对象的方式,而无需修改客户端代码。
优点:
- 解耦合:客户端代码与创建对象的具体实现分离,降低了耦合度。
- 扩展性:易于扩展以支持新的产品类型,只需添加新的具体工厂和产品类即可,无需修改现有代码。
- 管理复杂对象创建:可以封装复杂的对象创建逻辑,使客户端代码更加简洁和易于维护。
适用场景:
- 当一个类不知道它所需要的对象的类时。
- 当一个类希望由它的子类来指定所创建的对象时。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且希望动态决定所创建对象时。
工厂模式可以根据其实现方式和结构的不同,分为三种主要的分类:简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂模式
简单工厂模式是一种创建型设计模式,它提供了一个统一的接口来创建不同类型的对象,而无需暴露对象创建的具体逻辑。在简单工厂模式中,有一个工厂类负责根据客户端的需求创建相应的产品对象。
基本结构:
产品接口(Product Interface):定义了工厂方法所创建的对象的接口。
具体产品类(Concrete Products):实现了产品接口的具体产品类。
工厂类(Factory Class):包含一个工厂方法,根据客户端的需求创建并返回具体产品类的实例。
应用场景
解决接口选择问题
//抽象汽车
class AbstractCar
{public:virtual void ShowCarName = 0;
}; //具体产品的汽车继承抽象汽车类,并对其方法进行重写
//凯美瑞
class Camry: public AbstractCar
{void ShowCarName override(){cont<<"Camry Car"<< endl;}
};//迈腾
class Magotan: public AbstractCar
{void ShowCarName override(){cout<<"Magotan Car"<<endl;}
};//通过传递过来的参数来确定需要生产那种汽车
//汽车工厂
class CarFactory
{public:static AbstractCar* CreateCarFunc(string cname){if(cname == "Camary"){return new Camary;}else if(cname == "Magotan"){return new Magotan;}elsereturn nullptr;}
}int main()
{//创建工厂carFactory *fty = new carFactory;//创建汽车AbstractCar* Acar;//指定工厂需要创建的汽车Acar = fty->CreateCarFunc("Magotan");//获取指定车对象Acar->showCarName;delete Acar;Acar = fty->CreateCarFunc("Camry");//获取指定车对象Acar->showCarName;delete Acar;return 0;
}
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
工厂模式中的每一种形态都是针对一定问题的解决方案,工厂方法针对的是多个产品系列结构,而抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列。
在抽象工厂模式中,客户端不再负责对象的创建,而是把这个责任丢给具体的工厂类,客户端只负责对对象的调用,从而明确各个类的职责
抽象工厂四种角色
- 抽象工厂角色
- 具体工厂角色
- 抽象产品角色
- 具体产品角色
代码示例
#include<iostream>
using namespace std;//抽象西瓜
class AbstractWatermelon()
{public:virtual void PrintName() = 0;AbstractWatermelon(){cout<<"抽象西瓜的构造函数"<<endl;}~AbstractWatermelon(){cout<<"抽象西瓜的析构函数"<<endl;}
};//抽象橘子
class AbstractOrange()
{public:virtual void PrintName() = 0;AbstractOrange(){cout<<"抽象橘子的构造函数"<<endl;}~AbstractOrange(){cout<<"抽象橘子的析构函数"<<endl;}};//中国西瓜
class ChineseWatermelon: public AbstractWatermelon()
{public:void PrintName () override{cout<<"中国西瓜"<<endl;}ChineseWatermelon(){cout<<"中国西瓜的构造函数"<<endl;}~ChineseWatermelon(){cout<<"中国西瓜的析构函数 "<<endl;}
};//中国橘子
class ChineseOrange: public AbstractOrange
{public:void PrintName() override{cout<<"抽象中国橘子"<<endl;}ChineseOrange(){cout<<"中国橘子构造函数"<<endl;}~ChineseOrange(){cout<<"中国橘子析构函数"<<endl;}
};//埃及西瓜
class EgyptWatermelon: public AbstractWatermelon()
{public:void PrintName () override{cout<<"埃及西瓜"<<endl;}EgyptWatermelon(){cout<<"埃及西瓜的构造函数"<<endl;}~EgyptWatermelon(){cout<<"埃及西瓜的析构函数 "<<endl;}
};//埃及橘子
class EgyptOrange: public AbstractOrange
{public:void PrintName() override{cout<<"埃及橘子"<<endl;}EgyptOrange(){cout<<"埃及橘子构造函数"<<endl;}~EgyptOrange(){cout<<"埃及橘子析构函数"<<endl;}
};//抽象工厂 主要针对产品转换
class AbstractFactory
{public:virtual AbstractWatermelon* CreateWatermelon() = 0;virtual AbstractOrange* CreateOrange() = 0;AbstractFactory(){cout<<"抽象工厂构造函数"<<endl;}~AbstractFactory(){cout<<"抽象工厂析构函数"<<endl;}};//中国工厂
class ChinaFactory: public AbstractFactory
{public:AbstractWatermelon* CreateWatermelon() override{return new ChineseWatermelon;}AbstractOrange* CreateOrange() override{return new ChineseOrange;}ChinaFactory(){}~ChinaFactory(){}};//埃及工厂
class EgyptFactory: public AbstractFactory
{public:AbstractWatermelon* CreateWatermelon() override{return new EgyptWatermelon;}AbstractOrange* CreateOrange() override{return new EgyptOrange;}EgyptFactory(){}~EgyptFactory(){}
};int main()
{//中国工厂AbstractFactory* cfactory = new ChinaFactory;AbstractWatermelon *cwatermelon = cfactory->CreateWatermelon();AbstractOrange *corange = cfactory->CreateOrange();cwatermelon->PrintName();corange->PrintName();delete corange;corange = nullptr;delete cwatermelon;cwatermelon = nullptr;delete cfactory;cfactory = nullptr;return 0;
}