【C++设计模式】工厂方法模式

本文详细介绍了工厂方法模式,包括其优点(如隐藏产品创建细节、增强系统扩展性)和缺点(如增加系统复杂度)。通过UML类图展示了角色关系,并给出具体的产品和工厂类实现。在客户端代码中,通过多态性调用不同工厂创建所需产品,实现了开闭原则。总结指出,工厂方法模式是常用的设计模式,适用于不暴露产品创建细节的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习总结

  • 工厂方法模式的优点:
    • 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;
    • 工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象内部,多态性设计是工厂方法模式的关键;
    • 新加入产品时,无需修改原有代码,增强了系统的可扩展性,符合开闭原则
  • 工厂方法模式的缺点:
    • 添加新产品时需要同时添加新的产品工厂,系统中类的数量成对增加,增加了系统的复杂度,更多的类需要编译和运行,增加了系统的额外开销;
    • 工厂和产品都引入了抽象层,客户端代码中均使用的抽象层(AbstractFactoryAbstractSportProduct),增加了系统的抽象层次和理解难度。
  • 使用环境:
    • 客户端不需要知道它所需要创建的对象的类;
    • 抽象工厂类通过其子类来指定创建哪个对象(运用多态性设计和里氏代换原则)。

一、工厂方法模式

之前的简单工厂模式的最大问题:违背“开闭”原则,每当增加新的产品时,需要修改工厂类的逻辑。工厂方法模式不再使用工厂类统一创建所有的具体产品,而是让每个工厂只生产特定的产品。即让一个类的实例化延迟到其子类。

1.1 工厂方法模式的角色

  • 抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法;
  • 具体工厂(ConcreteFactory):生产具体的产品
  • 抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
  • 具体产品(ConcreteProduct):具体的产品类

1.2 UML类图

在这里插入图片描述
场景:客户Jungle想拿篮球就去篮球保管室,而不是像简单工厂模式,直接去一个保管所有体育器材的体育保管室:
在这里插入图片描述
如果对UML类图关系和符号忘了的童鞋可以复习下 【设计模式】UML类图关系与符号,大概就是:

  • 类的继承是用空心三角和实线,空心三角指向父类,如下面的具体的篮球工厂类BasketballFactory继承基类(抽象工厂类)AbstractFactory;再比如具体的篮球产品类Basketball继承基类(对应的篮球工厂类``)

在这里插入图片描述

二、代码实现

2.1 抽象产品类

定义抽象产品类AbstractSportProduct,方法不提供实现。

//抽象产品类AbstractProduct
class AbstractSportProduct{
public:
	AbstractSportProduct(){}
	//抽象方法:
	void printName(){};
	void play(){};
};

2.2 三个具体产品类

//三个具体产品类
//具体产品类Basketball
class Basketball :public AbstractSportProduct{
public:
	Basketball(){
		printName();
		play();
	}
	//具体实现方法
	void printName(){
		printf("Jungle get Basketball\n");
	}
	void play(){
		printf("Jungle play Basketball\n\n");
	}
};
 
//具体产品类Football
class Football :public AbstractSportProduct{
public:
	Football(){
		printName();
		play();
	}
	//具体实现方法
	void printName(){
		printf("Jungle get Football\n");
	}
	void play(){
		printf("Jungle play Football\n\n");
	}
};
 
//具体产品类Volleyball
class Volleyball :public AbstractSportProduct{
public:
	Volleyball(){
		printName();
		play();
	}
	//具体实现方法
	void printName(){
		printf("Jungle get Volleyball\n");
	}
	void play(){
		printf("Jungle play Volleyball\n\n");
	}
};

2.3 定义抽象工厂类

定义抽象工厂类AbstractFactory,其中的getSportProduct()方法为纯虚方法。

//抽象工厂类
class AbstractFactory{
public:
	//纯虚函数
	virtual AbstractSportProduct *getSportProduct() = 0;
};

2.4 三个具体工厂

//定义三个具体工厂类
//具体工厂类BasketballFactory
class BasketballFactory :public AbstractFactory{
public:
	BasketballFactory(){
		printf("BasketballFactory\n");
	}
	AbstractSportProduct *getSportProduct(){
		printf("basketball");
		return new Basketball();
	}
};

//具体工厂类FootballFactory
class FootballFactory :public AbstractFactory{
public:
	//构造函数
	FootballFactory(){
		printf("FootballFactory\n");
	}
	AbstractSportProduct *getSportProduct(){
		return new Football();
	}
};

//具体工厂类VolleyballFactory
class VolleyballFactory :public AbstractFactory{
public:
	//构造函数
	VolleyballFactory(){
		printf("VolleyballFactory\n");
	}
	//抽象产品类,返回一个棒球对象的产品指针
	AbstractSportProduct *getSportProduct(){
		return new Volleyball();
	}
};

2.5 客户端代码

  • 首先定义工厂类对象和产品类对象指针;
  • 用该父类指针(抽象工厂类指针)指向子类对象(如篮球工厂对象),并且利用该指针调用getSportProduct(),该函数在父类中被定义为纯虚函数,并且在各自的子类(具体工厂子类)中进行实现。
#include <iostream>
#include "FactoryMethod.h"
 
int main(){
	printf("工厂方法模式\n");
	
	//定义工厂类对象和产品类对象
	AbstractFactory *fac = NULL;
	AbstractSportProduct *product = NULL;
 
	fac = new BasketballFactory();
	product = fac->getSportProduct();
 
	fac = new FootballFactory();
	product = fac->getSportProduct();
 
	fac = new VolleyballFactory();
	product = fac->getSportProduct();	
 
	system("pause");
	return 0;
}

在这里插入图片描述

三、工厂方法模式小结

  • 如果某客户想玩棒球,只需要增加一个棒球工厂BaseballFactory,然后在客户端代码中修改具体工厂类的类名,而原有的类的代码无需修改。
  • 和简单工厂模式相比,工厂方法模式更加符合开闭原则,也是使用频率最高的设计模式之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山顶夕景

小哥哥给我买个零食可好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值