简单工厂模式(Simple Factroy Pattern):定义一个工厂类,它可*根据参数的不同返回不同的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
Q 为什么工厂中的创建实例方法是静态方法
A 因为不需要使用创建对象的方法来实例化对象,因此可以使用静态方法来创建一个简单的工厂
需要什么,就像工厂传入一个正确的参数,就可以获得所需要的对象,而无需知道创建细节。UML图如下
图中要三个不同的角色:
Product(抽象产品角色)
class Operation {
public:
virtual double getResult(double A,double B) = 0;
};
ConcreteProduct(具体产品角色)
class Add : public Operation {
public:
virtual double getResult(double A, double B) {
return A + B;
}
};
class Sub : public Operation {
public:
virtual double getResult(double A, double B) {
return A - B;
}
};
class Mul : public Operation {
public:
virtual double getResult(double A, double B) {
return A * B;
}
};
class Div : public Operation {
public:
virtual double getResult(double A, double B) {
if(B == 0) cout << "除数不能为0" << endl;
else
return A / B;
}
};
Factory(工厂角色)
class EasyFactory {
public:
static Operation* createOperation(char src) {
Operation* op = nullptr;
switch(src) {
case '+':
op = new Add();
break;
case '-':
op = new Sub();
break;
case '*':
op = new Mul();
break;
case '/':
op = new Div();
break;
default:
cout << "输入错误" << endl;
}
return op;
}
};
客户端:
int main() {
Operation* add = EasyFactory::createOperation('+');
Operation* sub = EasyFactory::createOperation('-');
Operation* mul = EasyFactory::createOperation('*');
Operation* div = EasyFactory::createOperation('/');
cout << "2 + 2 = " << add->getResult(2,2) << endl;
cout << "2 - 2 = " << sub->getResult(2,2) << endl;
cout << "2 * 2 = " << mul->getResult(2,2) << endl;
cout << "2 / 2 = " << div->getResult(2,2) << endl;
return 0;
}
输出结果:
对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。
在工厂模式中,工厂父类负责定义创建产品对象的公告接口,而工厂子类负责生成具体的产品对象。目的是将产品的实例化操作延迟到工厂子类中完成,通过工厂子类来确定究竟应该实例化哪一个具体产品类。这相当于是把原本会因为业务代码而庞大的简单工厂类,拆分成了一个个的工厂类,这样代码就不会都耦合在同一个类里了(解耦)。
图中四个重要的角色:
具体工厂是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例。
Product抽象产品
class Operation {
public:
virtual double getResult(double A,double B) = 0;
};
ConcreteProduct具体产品
class Add : public Operation {
public:
virtual double getResult(double A, double B) {
return A + B;
}
};
class Sub : public Operation {
public:
virtual double getResult(double A, double B) {
return A - B;
}
};
class Mul : public Operation {
public:
virtual double getResult(double A, double B) {
return A * B;
}
};
class Div : public Operation {
public:
virtual double getResult(double A, double B) {
if(B == 0) cout << "除数不能为0" << endl;
else
return A / B;
}
};
Factory抽象工厂
class Factory {
public:
virtual Operation* createOperation() = 0;
};
ConcreteFactory具体工厂
class AddFactory : public Factory {
public:
virtual Operation* createOperation() {
cout << "加法运算" ;
return new Add();
}
};
class SubFactory : public Factory {
public:
virtual Operation* createOperation() {
cout << "减法运算" ;
return new Sub();
}
};
class MulFactory : public Factory {
public:
virtual Operation* createOperation() {
cout << "乘法运算" ;
return new Mul();
}
};
class DivFactory : public Factory {
public:
virtual Operation* createOperation() {
cout << "除法运算" ;
return new Div();
}
};
客户端:
int main() {
Factory * af = new AddFactory();
Operation* add = af->createOperation();
cout << "2 + 2 = " << add->getResult(2,2) << endl;
Factory * sf = new SubFactory();
Operation* sub = sf->createOperation();
cout << "2 - 2 = " << sub->getResult(2,2) << endl;
Factory * mf = new MulFactory();
Operation* mul = mf->createOperation();
cout << "2 * 2 = " << mul->getResult(2,2) << endl;
Factory * df = new DivFactory();
Operation* div = df->createOperation();
cout << "2 / 2 = " << div->getResult(2,2) << endl;
return 0;
}
系统的扩展性好,符合“开闭原则” 。系统加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品即可。
在添加新产品时,需要编写新的具体产品类,而且要提供与之对应的具体工厂类,系统中类的个数将成对增加,一定程度上增加了系统的复杂度。
工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型,它提供了一种创建对象的最佳方式。
角色:
抽象工厂(Abstract Factory):
class IDBFactory{
public:
virtual IDBConnection* CreateDBConnection()=0;
virtual IDBCommand* CreateDBCommand()=0;
virtual IDataReader* CreateDataReader()=0;
};
具体工厂(ConcreteFactory):
class SqlDBFactory:public IDBFactory{
public:
virtual IDBConnection* CreateDBConnection()=0;
virtual IDBCommand* CreateDBCommand()=0;
virtual IDataReader* CreateDataReader()=0;
};
class OracleDBFactory:public IDBFactory{
public:
virtual IDBConnection* CreateDBConnection()=0;
virtual IDBCommand* CreateDBCommand()=0;
virtual IDataReader* CreateDataReader()=0;
};
抽象产品(AbstractProduct):
//数据库访问有关的基类
class IDBConnection{
};
class IDBCommand{
};
class IDataReader{
};
具体产品(ConcreteProduct):
//支持SQL Server
class SqlConnection: public IDBConnection{
};
class SqlCommand: public IDBCommand{
};
class SqlDataReader: public IDataReader{
};
//支持Oracle
class OracleConnection: public IDBConnection{
};
class OracleCommand: public IDBCommand{
};
class OracleDataReader: public IDataReader{
};
客户端:
int main(){
IDBFactory *sqlFactory = new SqlDBFactory();
IDBFactory *oracleFactory = new OracleDBFactory();
// 创建实例
IDBComman* sqlCommand = SqlDBFactory->CreateDBCommand();
IDBConnect* sqlConnect = SqlDBFactory->CreateDBConnection();
IDataReader* sqlReader = SqlDBFactory->CreateDataReader();
IDBComman* oracleCommand = oracleFactory->CreateDBCommand();
IDBConnect* oracleConnect = oracleFactory->CreateDBConnection();
IDataReader* oracleReader = oracleFactory->CreateDataReader();
}
如上代码所示数据库相关内容,数据库操作有连接、指令、读取数据等。同时数据库有多种类型,比如说sqlServer、Oracle等,不同的数据库对应的指令操作、连接操作等大有不同。如果指令操作不能对应上数据库,那么就不能正常运行。这时候比较恰当的做法是把与数据库对应的操作封装在一起,使得相关组件达到高内聚的效果。
如果工厂中产品族中要增加一个新的产品时,所有的工厂类都要进行修改(具体工厂继承于抽象工厂)。增加了系统的抽象性和理解难度。
如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑,你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。