工厂方法模式
1、背景
在前面说明的简单工厂模式中,构造加减乘除四个类继承父类重写运算函数。产品看成是一系列类的集合,这些类是由某个抽象类或者接口派生出来的一个对象树。工厂类是整个模式的关键,包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.
如果要创建的产品不多,只要一个工厂类就可以完成。
如果我现在需要增加其他运算,比如求M数的N次方,或者求M数的N次方根,这些功能的增加,在简单工厂里,我是先去加‘求M数的N次方’功能类,然后去更改工厂方法,当中加‘Case’语句来做判断,违反了基类的开放封闭原则。
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
2、定义
1、定义:
一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
2、结构
- 1、抽象工厂(Abstract Factory)角色:是工厂方法模式的核心,与应用程序无关。提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法newProduct() 来创建产品。
- 2、具体工厂(Concrete Creator)角色: 这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
- 3、抽象产品(Product)角色: 定义了产品的规范,也就是产品对象的共同父类或共同拥有的接口
- 4、具体产品(Concrete Product)角色: 这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
3、特征
1、优点
- 开放封闭原则: 新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
- 单一职责原则 :每个具体工厂类只负责创建对应的产品,简单工厂中的工厂类存在复杂的switch逻辑判断
- 不使用静态工厂方法,可以形成基于继承的等级结构,简单工厂模式的工厂类使用静态工厂方法
- 屏蔽产品类。 产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不表,系统中的上层模块就不要发生变化,因为产品类的实例化工作是由工厂类负责,一个产品对象具体由哪一个产品生成是由工厂类决定的。
2、缺点
- 添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
- 虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;
- 一个具体工厂只能创建一种具体产品
3、应用场景:
- 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌。
4、应用
大话设计模式案例:四则运算计算器
- 1、简单工厂模式:
#include <iostream>
#include <string>
using namespace std;
//基类
class Operation
{
public:
double numberA, numberB;
virtual double getResult()
{
return 0;
}
};
//加法
class addOperation :public Operation
{
double getResult()
{
return numberA + numberB;
}
};
//减法
class subOperation :public Operation
{
double getResult()
{
return numberA - numberB;
}
};
//乘法
class mulOperation :public Operation
{
double getResult()
{
return numberA*numberB;
}
};
//除法
class divOperation :public Operation
{
double getResult()
{
return numberA / numberB;
}
};
//工厂类
class operFactory
{
public:
static Operation *createOperation(char c)
{
switch (c)
{
case '+':
return new addOperation;
break;
case '-':
return new subOperation;
break;
case '*':
return new mulOperation;
break;
case '/':
return new divOperation;
break;
}
}
};
int main()
{
Operation *oper = operFactory::createOperation('+');
oper->numberA = 9;
oper->numberB = 99;
cout << oper->getResult() << endl;
return 0;
}
2、工厂方法模式:
#include <iostream>
#include <string>
using namespace std;
class Operation
{
public:
double numberA, numberB;
virtual double getResult()
{
return 0;
}
};
class addOperation :public Operation
{
double getResult()
{
return numberA + numberB;
}
};
class subOperation :public Operation
{
double getResult()
{
return numberA - numberB;
}
};
class mulOperation :public Operation
{
double getResult()
{
return numberA*numberB;
}
};
class divOperation :public Operation
{
double getResult()
{
return numberA / numberB;
}
};
class IFactory
{
public:
virtual Operation *createOperation() = 0;
};
class AddFactory :public IFactory
{
public:
static Operation *createOperation()
{
return new addOperation();
}
};
class SubFactory :public IFactory
{
public:
static Operation *createOperation()
{
return new subOperation();
}
};
class MulFactory :public IFactory
{
public:
static Operation *createOperation()
{
return new mulOperation();
}
};
class DivFactory :public IFactory
{
public:
static Operation *createOperation()
{
return new divOperation();
}
};
int main()
{
Operation *oper = MulFactory::createOperation();
oper->numberA = 9;
oper->numberB = 99;
cout << oper->getResult() << endl;
return 0;
}
3、雷锋工厂:
#include <iostream>
#include <string>
using namespace std;
//实例基类,相当于Product(为了方便,没用抽象)
class LeiFeng
{
public:
virtual void sweep()
{
cout << "雷锋扫地" << endl;
}
void wash()
{
cout << "雷锋洗衣服" << endl;
}
};
//学雷锋的大学生,相当于ConcreteProduct
class Student :public LeiFeng
{
public:
virtual void sweep() {
cout << "大学生扫地" << endl;
}
};
//学雷锋的志愿者,相当于ConcreteProduct
class Volunteer :public LeiFeng
{
public:
virtual void sweep() {
cout << "志愿者扫地" << endl;
}
};
//工厂基类Creator
class LeiFengFactory
{
public:
virtual LeiFeng *createLeiFeng()
{
return new LeiFeng();
}
};
//工厂具体类
class StudentFactory :public LeiFengFactory
{
public:
virtual LeiFeng *createLeiFeng()
{
return new Student();
}
};
class VolFactory :public LeiFengFactory
{
public:
virtual LeiFeng *createLeiFeng()
{
return new Volunteer();
}
};
int main()
{
LeiFengFactory *sf = new VolFactory();
LeiFeng *s = sf->createLeiFeng();
s->sweep();
delete s;
delete sf;
return 0;
}
参考
1、https://blog.csdn.net/varyall/article/details/82355964
2、http://c.biancheng.net/view/1348.html
3、《大话设计模式 》