【C++设计模式】工厂方法模式
【摘要】
学习总结
工厂方法模式的优点:
工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象...
学习总结
- 工厂方法模式的优点:
- 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;
- 工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象内部,多态性设计是工厂方法模式的关键;
- 新加入产品时,无需修改原有代码,增强了系统的可扩展性,符合开闭原则。
- 工厂方法模式的缺点:
- 添加新产品时需要同时添加新的产品工厂,系统中类的数量成对增加,增加了系统的复杂度,更多的类需要编译和运行,增加了系统的额外开销;
- 工厂和产品都引入了抽象层,客户端代码中均使用的抽象层(
AbstractFactory
和AbstractSportProduct
),增加了系统的抽象层次和理解难度。
- 使用环境:
- 客户端不需要知道它所需要创建的对象的类;
- 抽象工厂类通过其子类来指定创建哪个对象(运用多态性设计和里氏代换原则)。
一、工厂方法模式
之前的简单工厂模式的最大问题:违背“开闭”原则,每当增加新的产品时,需要修改工厂类的逻辑。工厂方法模式不再使用工厂类统一创建所有的具体产品,而是让每个工厂只生产特定的产品。即让一个类的实例化延迟到其子类。
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(){};
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
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");
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
2.3 定义抽象工厂类
定义抽象工厂类AbstractFactory
,其中的getSportProduct()
方法为纯虚方法。
//抽象工厂类
class AbstractFactory{
public:
//纯虚函数
virtual AbstractSportProduct *getSportProduct() = 0;
};
- 1
- 2
- 3
- 4
- 5
- 6
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();
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
三、工厂方法模式小结
- 如果某客户想玩棒球,只需要增加一个棒球工厂
BaseballFactory
,然后在客户端代码中修改具体工厂类的类名,而原有的类的代码无需修改。 - 和简单工厂模式相比,工厂方法模式更加符合开闭原则,也是使用频率最高的设计模式之一。
文章来源: andyguo.blog.csdn.net,作者:山顶夕景,版权归原作者所有,如需转载,请联系作者。
原文链接:andyguo.blog.csdn.net/article/details/122962585
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)