一、什么是工厂
- 设计一个抽象产品类,它包含一些公共方法的声明
- 从抽象产品类中派生出多个具体产品类,具体产品类中实现具体产品生产的相关代码
- 设计一个工厂类,工厂类提供一个生产各种产品的创建方法,该方法根据传入参数(产品名称)创建不同的具体产品类对象
- 应用只需调用工厂类的这个创建方法,无需知道具体产品的类名,并传入具体产品参数,即可得到一个具体产品对象。
工厂模式细分为三种:简单工厂模式、工厂方法模式、抽象工厂模式。
二、 简单工厂模式
简单工厂模式是最简单的设计模式之一,其实它并不属于GOF的23种设计模式,但应用也十分频繁,同时也是其余创建型模式的基础,因此有必要先学习简单工厂模式。
UML类图
简单工厂模式结构
- Factory (工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象; 在工厂类中提供了静态的工厂方法factoryMethod(),它的返回类型为抽象产品类型Product。
- Product(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。
- ConcreteProduct(具体产品角色):它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。
代码
一、定义抽象产品类AbstractProduct
animals类:动物类(AbstractProduct)
class animals_s {
public:
animals_s() {
}
virtual int get_leg_num() {
return m_leg_num;
}
virtual string get_color() {
return m_color;
}
virtual ~animals_s() {
};
protected:
int m_leg_num;
string m_color;
};
二、定义具体产品类
dog类:小狗动物类(Product1)
class dog_s : public animals_s {
public:
dog_s() : animals_s() {
m_leg_num = 4;
m_color = "write";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~dog_s() {
}
};
cock类:小鸡动物类(Product2)
class cock_s : public animals_s {
public:
cock_s() : animals_s() {
m_leg_num = 2;
m_color = "black";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~cock_s() {
}
};
三、定义工厂类和工厂方法
animals_factory_s类:动物生产工厂类(Factory)
class animals_factory_s {
public:
animals_s *create_animals(const string &animals_type) {
animals_s *p_animals_obj = nullptr;
if (animals_type == "dog_s") {
p_animals_obj = new dog_s();
} else if (animals_type == "cock_s") {
p_animals_obj = new cock_s();
}
return p_animals_obj;
}
};
应用
int main(int argc, char** argv) {
unique_ptr<animals_factory_s> m_animals_factory(new animals_factory_s());
unique_ptr<animals_s> dog(m_animals_factory->create_animals("dog_s"));
unique_ptr<animals_s> cock(m_animals_factory->create_animals("cock_s"));
int dog_leg_num;
string dog_color;
if (dog != NULL) {
dog_leg_num = dog->get_leg_num();
dog_color = dog->get_color();
}
int cock_leg_num;
string cock_color;
if (cock != NULL) {
cock_leg_num = cock->get_leg_num();
cock_color = cock->get_color();
}
return 0;
}
扩展
增加小猫动物。
一、扩展具体产品类
cat类:小猫动物类(Product3)
class cat_s : public animals_s {
public:
cat_s() : animals_s() {
m_leg_num = 4;
m_color = "grey";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~cat_s() {
}
};
二、扩展工厂类方法
animals_factory_s类:动物生产工厂类(Factory)
![](/qrcode.jpg)
class animals_factory_s {
public:
animals_s *create_animals(const string &animals_type) {
animals_s *p_animals_obj = nullptr;
if (animals_type == "dog_s") {
AINFO << "create dog_s class ";
p_animals_obj = new dog_s();
} else if (animals_type == "cock_s") {
AINFO << "create cock_s class ";
p_animals_obj = new cock_s();
} else if (animals_type == "cat_s") {
AINFO << "create cat_s class ";
p_animals_obj = new cat_s();
}
return p_animals_obj;
}
};
三、扩展应用
int main(int argc, char** argv) {
unique_ptr<animals_factory_s> m_animals_factory(new animals_factory_s());
unique_ptr<animals_s> dog(m_animals_factory->create_animals("dog_s"));
unique_ptr<animals_s> cock(m_animals_factory->create_animals("cock_s"));
unique_ptr<animals_s> cat(m_animals_factory->create_animals("cat_s"));
int dog_leg_num;
string dog_color;
if (dog != NULL) {
dog_leg_num = dog->get_leg_num();
dog_color = dog->get_color();
}
int cock_leg_num;
string cock_color;
if (cock != NULL) {
cock_leg_num = cock->get_leg_num();
cock_color = cock->get_color();
}
int cat_leg_num;
string cat_color;
if (cat != NULL) {
cat_leg_num = cat->get_leg_num();
cat_color = cat->get_color();
}
return 0;
}
优点
- 一个调用者想创建一个对象,只要知道其名称就可以了(应用中的"MiPhone"、“iPhone”、“HuaweiPhone”);
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以(参照扩展的内容);
- 屏蔽产品的具体实现,调用者只关心产品的接口,实现了创建对象的代码(工厂类的makePhone),与具体的类(手机产品)解耦合的效果。。
缺点
- 扩展性差(实例中想增加一种手机产品,除了新增一个手机产品类,还需要修改工厂类方法)这样一来,就需要修改源代码,灵活性非常的差,且违背“开闭原则”。
- 不同的产品需要不同额外参数的时候 不支持。
使用场合
- 在程序中,需要创建的对象很多,导致对象的new操作多且杂时,需要使用简单工厂模式。
- 由于对象的创建过程是我们不需要去关心的,而我们注重的是对象的实际操作,所以,我们需要分离对象的创建和操作两部分,如此,方便后期的程序扩展和维护。
三、工厂方法模式
工厂方法模式是使用频率最高的工厂模式。
定义一个用于创建对象的接口(virtual animals_m *create_animals() = 0;),但是让子类决定将哪一个类实例化(子类实现create_animals)。工厂方法模式让一个类的实例化延迟到其子类。
简单工厂模式中,每新增一个具体产品,就需要修改工厂类内部的判断逻辑。为了不修改工厂类,遵循开闭原则,工厂方法模式中不再使用工厂类统一创建所有的具体产品,而是针对不同的产品设计了不同的工厂,每一个工厂只生产特定的产品。
UML类图
工厂方法模式结构
从工厂方法模式简介中,可以知道该模式有以下几种角色:
- 抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法
- 具体工厂(ConcreteFactory):生产具体产品的工厂
- 抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
- 具体产品(ConcreteProduct):具体的产品类
代码
一、定义抽象产品类AbstractProduct(和简单工厂一致)
animals类:动物类(AbstractProduct)
class animals_m {
public:
animals_m() {
}
virtual int get_leg_num() {
return m_leg_num;
}
virtual string get_color() {
return m_color;
}
virtual ~animals_m(){
};
protected:
int m_leg_num;
string m_color;
};
二、定义具体产品类(和简单工厂一致)
dog类:小狗动物类(Product1)
class dog_m : public animals_m {
public:
dog_m() : animals_m() {
m_leg_num = 4;
m_color = "write";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~dog_m() {
}
};
cock类:小鸡动物类(Product2)
class cock_m : public animals_m {
public:
cock_m() : animals_m() {
m_leg_num = 2;
m_color = "black";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~cock_m() {
}
};
三、定义抽象工厂类AbstractFactory
定义一个用于创建对象的接口(virtual animals_m *create_animals() = 0;),当需要扩展时,不需要更改此文件。
AbstractFactory类:生产不同产品的工厂的抽象类
class animals_factory_m {
public:
virtual animals_m *create_animals() = 0;
virtual ~animals_factory_m() {
}
};
四、定义具体工厂类
让子类决定将哪一个类实例化(子类实现create_animals)
dog_factory_m类:生产小狗动物的工厂类(ConcreteFactory1)
class dog_factory_m : public animals_factory_m
{
public:
animals_m *create_animals() {
return new dog_m();
}
};
cock_factory_m类:生产小鸡动物的工厂类(ConcreteFactory2)
class cock_factory_m : public animals_factory_m
{
public:
animals_m *create_animals() {
return new cock_m();
}
};
五、应用
int main(int argc, char** argv) {
unique_ptr<animals_factory_m> m_dog_factory(new dog_factory_m());
unique_ptr<animals_factory_m> m_cock_factory(new cock_factory_m());
unique_ptr<animals_m> cock(m_cock_factory->create_animals());
unique_ptr<animals_m> dog(m_dog_factory->create_animals());
int dog_leg_num;
string dog_color;
if (dog != NULL) {
dog_leg_num = dog->get_leg_num();
dog_color = dog->get_color();
}
int cock_leg_num;
string cock_color;
if (cock != NULL) {
cock_leg_num = cock->get_leg_num();
cock_color = cock->get_color();
}
}
扩展
一、扩展具体产品类
cat类:小猫动物类(Product3)
class cat_m : public animals_m {
public:
cat_m() : animals_m() {
m_leg_num = 4;
m_color = "grey";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~cat_m() {
}
};
二、扩展具体工厂类
cat_factory_m类:生产小猫动物的工厂类(ConcreteFactory3)
class cat_factory_m : public animals_factory_m
{
public:
animals_m *create_animals() {
return new cat_m();
}
};
三、扩展应用
int main(int argc, char** argv) {
unique_ptr<animals_factory_m> m_dog_factory(new dog_factory_m());
unique_ptr<animals_m> dog(m_dog_factory->create_animals());
int dog_leg_num;
string dog_color;
if (dog != NULL) {
dog_leg_num = dog->get_leg_num();
dog_color = dog->get_color();
}
unique_ptr<animals_factory_m> m_cock_factory(new cock_factory_m());
unique_ptr<animals_m> cock(m_cock_factory->create_animals());
int cock_leg_num;
string cock_color;
if (cock != NULL) {
cock_leg_num = cock->get_leg_num();
cock_color = cock->get_color();
}
unique_ptr<animals_factory_m> m_cat_factory(new cat_factory_m());
unique_ptr<animals_m> cat(m_cat_factory->create_animals());
int cat_leg_num;
string cat_color;
if (cat != NULL) {
cat_leg_num = cat->get_leg_num();
cat_color = cat->get_color();
}
}
四、增加模板类
我们每实现一个动物类,就需要实现一个对应的动物工厂类,有点麻烦,其实我们可以通过模板来优化这一步操作。
template <class T>
class factory_t_m : public animals_factory_m
{
public:
virtual animals_m *create_animals() {
return new T();
}
};
五、修改应用
int main(int argc, char** argv) {
unique_ptr<animals_factory_m> m_dog_factory(new factory_t_m<dog_m>());
unique_ptr<animals_m> dog(m_dog_factory->create_animals());
int dog_leg_num;
string dog_color;
if (dog != NULL) {
dog_leg_num = dog->get_leg_num();
dog_color = dog->get_color();
}
unique_ptr<animals_factory_m> m_cock_factory(new factory_t_m<cock_m>());
unique_ptr<animals_m> cock(m_cock_factory->create_animals());
int cock_leg_num;
string cock_color;
if (cock != NULL) {
cock_leg_num = cock->get_leg_num();
cock_color = cock->get_color();
}
unique_ptr<animals_factory_m> m_cat_factory(new factory_t_m<cat_m>());
unique_ptr<animals_m> cat(m_cat_factory->create_animals());
int cat_leg_num;
string cat_color;
if (cat != NULL) {
cat_leg_num = cat->get_leg_num();
cat_color = cat->get_color();
}
}
使用模版,在增加动物类时,可以不增加动物工厂类,但是在应用中,需要知道动物类的类名(unique_ptr<animals_factory_m> m_cat_factory(new factory_t_m<cat_m>()))
优点
- 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂。
- 工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象内部,多态性设计是工厂方法模式的关键。
- 新加入产品时,无需修改原有代码,增强了系统的可扩展性,符合开闭原则。
缺点
- 添加新产品时需要同时添加新的产品工厂,系统中类的数量成对增加,增加了系统的复杂度,更多的类需要编译和运行,增加了系统的额外开销。
四、抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
简言之,一个工厂可以提供创建多种相关产品的接口,而无需像工厂方法一样,为每一个产品都提供一个具体工厂。
UML类图
抽象工厂模式结构
抽象工厂模式结构与工厂方法模式结构类似,不同之处在于,一个具体工厂可以生产多种同类相关的产品:
- 抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法
- 具体工厂(ConcreteFactory):生产具体产品的工厂
- 抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
- 具体产品(ConcreteProduct):具体的产品类
需求
在工厂方法模式基础上,增加系列,比如山地动物,河边动物,丛林动物,那么我们之前的例子就可以分为
山地 | 河边 | 丛林 |
---|---|---|
狗 | 狗 | 狗 |
鸡 | 鸡 | 鸡 |
猫 | 猫 | 猫 |
代码
一、定义A类抽象产品类AbstractProductA
山地动物类:定义山地动物的接口(AbstractPhoneA)
class hill_animals {
public:
hill_animals() {
}
virtual int get_leg_num() {
return m_leg_num;
}
virtual string get_color() {
return m_color;
}
virtual ~hill_animals(){
};
protected:
int m_leg_num;
string m_color;
};
二、定义具体A类产品类
hill_dog类:山地小狗动物类(Product1)
class hill_dog : public hill_animals {
public:
hill_dog() : hill_animals() {
m_leg_num = 4;
m_color = "black";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~hill_dog() {
}
};
hill_cock类:山地小鸡动物类(Product2)
class hill_cock : public hill_animals {
public:
hill_cock() : hill_animals() {
m_leg_num = 2;
m_color = "black";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~hill_cock() {
}
};
hill_cat类:山地小猫动物类(Product3)
class hill_cat : public hill_animals {
public:
hill_cat() : hill_animals() {
m_leg_num = 4;
m_color = "black";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~hill_cat() {
}
};
三、定义B类抽象产品类AbstractProductB
河边动物类:定义河边动物的接口(AbstractPhoneB)
class river_animals {
public:
river_animals() {
}
virtual int get_leg_num() {
return m_leg_num;
}
virtual string get_color() {
return m_color;
}
virtual ~river_animals(){
};
protected:
int m_leg_num;
string m_color;
};
四、定义具体B类产品类
river_dog 类:河流小狗动物类(Product1)
class river_dog : public river_animals {
public:
river_dog() : river_animals() {
m_leg_num = 4;
m_color = "white";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~river_dog() {
}
};
river_cock 类:河流小鸡动物类(Product2)
class river_cock : public river_animals {
public:
river_cock() : river_animals() {
m_leg_num = 2;
m_color = "white";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~river_cock() {
}
};
river_cat 类:河流小猫动物类(Product3)
class river_cat : public river_animals {
public:
river_cat() : river_animals() {
m_leg_num = 4;
m_color = "white";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~river_cat() {
}
};
五、定义C类抽象产品类AbstractProductC
丛林动物类:定义丛林动物的接口(AbstractPhoneC)
class jungle_animals {
public:
jungle_animals() {
}
virtual int get_leg_num() {
return m_leg_num;
}
virtual string get_color() {
return m_color;
}
virtual ~jungle_animals(){
};
protected:
int m_leg_num;
string m_color;
};
六、定义具体C类产品类
jungle_dog类:丛林小狗动物类(Product1)
class jungle_dog : public jungle_animals {
public:
jungle_dog() : jungle_animals() {
m_leg_num = 4;
m_color = "green";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~jungle_dog() {
}
};
jungle_cock类:丛林小鸡动物类(Product2)
class jungle_cock : public jungle_animals {
public:
jungle_cock() : jungle_animals() {
m_leg_num = 2;
m_color = "green";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~jungle_cock() {
}
};
jungle_cat 类:丛林小猫动物类(Product3)
class jungle_cat : public jungle_animals {
public:
jungle_cat() : jungle_animals() {
m_leg_num = 4;
m_color = "green";
}
int get_leg_num() {
return m_leg_num;
}
string get_color() {
return m_color;
}
virtual ~jungle_cat() {
}
};
七、定义抽象工厂AbstractFactory
class animals_factory_a {
public:
virtual hill_animals *create_hill_animals() = 0;
virtual river_animals *create_river_animals() = 0;
virtual jungle_animals *create_jungle_animals() = 0;
virtual ~animals_factory_a() {
}
};
八、定义具体工厂ConcreteProduct
小狗工厂类
class dog_factory : public animals_factory_a
{
public:
virtual hill_animals *create_hill_animals() {
return new hill_dog();
}
virtual river_animals *create_river_animals() {
return new river_dog();
}
virtual jungle_animals *create_jungle_animals() {
return new jungle_dog();
}
};
小鸡工厂类
class cock_factory : public animals_factory_a
{
public:
virtual hill_animals *create_hill_animals() {
return new hill_cock();
}
virtual river_animals *create_river_animals() {
return new river_cock();
}
virtual jungle_animals *create_jungle_animals() {
return new jungle_cock();
}
};
小猫工厂类
class cat_factory : public animals_factory_a
{
public:
virtual hill_animals *create_hill_animals() {
return new hill_cat();
}
virtual river_animals *create_river_animals() {
return new river_cat();
}
virtual jungle_animals *create_jungle_animals() {
return new jungle_cat();
}
};
九、应用
int main(int argc, char** argv) {
unique_ptr<animals_factory_a> dog_bank(new dog_factory());
unique_ptr<hill_animals> hill_dog(dog_bank->create_hill_animals());
unique_ptr<river_animals> river_dog(dog_bank->create_river_animals());
unique_ptr<jungle_animals> jungle_dog(dog_bank->create_jungle_animals());
int dog_leg_num;
string dog_color;
if (hill_dog != NULL) {
dog_leg_num = hill_dog->get_leg_num();
dog_color = hill_dog->get_color();
}
if (river_dog != NULL) {
dog_leg_num = river_dog->get_leg_num();
dog_color = river_dog->get_color();
}
if (jungle_dog != NULL) {
dog_leg_num = jungle_dog->get_leg_num();
dog_color = jungle_dog->get_color();
}
unique_ptr<animals_factory_a> cock_bank(new cock_factory());
unique_ptr<hill_animals> hill_cock(cock_bank->create_hill_animals());
unique_ptr<river_animals> river_cock(cock_bank->create_river_animals());
unique_ptr<jungle_animals> jungle_cock(cock_bank->create_jungle_animals());
int cock_leg_num;
string cock_color;
if (hill_dog != NULL) {
cock_leg_num = hill_cock->get_leg_num();
cock_color = hill_cock->get_color();
}
if (river_dog != NULL) {
cock_leg_num = river_cock->get_leg_num();
cock_color = river_cock->get_color();
}
if (jungle_dog != NULL) {
cock_leg_num = jungle_cock->get_leg_num();
cock_color = jungle_cock->get_color();
}
unique_ptr<animals_factory_a> cat_bank(new cat_factory());
unique_ptr<hill_animals> hill_cat(cat_bank->create_hill_animals());
unique_ptr<river_animals> river_cat(cat_bank->create_river_animals());
unique_ptr<jungle_animals> jungle_cat(cat_bank->create_jungle_animals());
int cat_leg_num;
string cat_color;
if (hill_dog != NULL) {
cat_leg_num = hill_dog->get_leg_num();
cat_color = hill_dog->get_color();
}
if (river_dog != NULL) {
cat_leg_num = river_cat->get_leg_num();
cat_color = river_cat->get_color();
}
if (jungle_dog != NULL) {
cat_leg_num = jungle_cat->get_leg_num();
cat_color = jungle_cat->get_color();
}
}
优点
抽象工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂。
新加入产品系列时,无需修改原有系统,增强了系统的可扩展性,符合开闭原则。
缺点
在已有产品系列中添加新产品时需要修改抽象层代码,对原有系统改动较大,违背开闭原则。