概念和介绍
工厂设计模式定义了创建对象的接口,允许子类决定实例化哪个类,而且允许请求者无须知道要被实例化的特定类,这样可以在不修改代码的情况下引入新类。
工厂设计模式优点:
(1)没有了将应用程序类绑定到代码中的要求,可以使用任何实现了接口的类
(2) 允许子类提供对象的扩展版本。
工厂设计模式的应用场景:
(1)类不能预料它必须创建的对象的类;
(2)类希望其子类指定它要创建的对象。
场景举例:
应用程序设计中,数据库访问需要良好的封装性和可维护性,因此经常使用工厂设计模式来实现对数据库访问的封装。
在数据访问层定义采用工厂模式,定义统一的操纵数据库的接口,然后根据数据库的不同,由类工厂来决定实例化哪个类。在具体类中实现特定的数据库访问类。这样,就可以实现由客户端指定或根据配置文件来选择访问不同的数据库,从而实现应用程序与数据库无关。
分类
工厂设计模式主要有如下几种:
一、简单工厂(Simple Factory)模式
代码实现:根据输入,返回创建的对象。通常只有一个工厂类。
使用一个专门的工厂负责生产对象,这个工厂类定义一个用于创建产品的静态接口,直接通过调用工厂类那个方法的方式获取需要的对象。可以定义不同的接口生产不同的对象,也可以定义一个接口通过函数参数生成不同对象。简单工厂生产的产品是统一的抽象产品,方便外部调用者可以提供通用的处理方式。一个工厂类来统一负责所有产品的创建。
优点:新添加类时,不会影响以前的系统代码。适用于不同情况创建不同的类时。
缺点:客户端必须要知道基类和工厂类,耦合性差。
示例代码和类图:
#include <string>
#include <iostream>
using namespace std;
//基类
class COperation
{
public:
int m_nFirst;
int m_nSecond;
virtual double GetResult()
{
double dResult=0;
return dResult;
}
};
//加法
class AddOperation : public COperation
{
public:
virtual double GetResult()
{
return m_nFirst+m_nSecond;
}
};
//减法
class SubOperation : public COperation
{
public:
virtual double GetResult()
{
return m_nFirst-m_nSecond;
}
};
//工厂类
class CCalculatorFactory
{
public:
static COperation* Create(char cOperator);
};
COperation* CCalculatorFactory::Create(char cOperator)
{
COperation *oper;
switch (cOperator)
{
case '+':
oper=new AddOperation();
break;
case '-':
oper=new SubOperation();
break;
default:
oper=new AddOperation();
break;
}
return oper;
}
//客户端
int main()
{
int a,b;
cin>>a>>b;
COperation * op=CCalculatorFactory::Create('-');
op->m_nFirst=a;
op->m_nSecond=b;
cout<<op->GetResult()<<endl;
return 0;
}
二、工厂方法(Factory Method)模式
代码实现:有一个工厂方法接口,有多个工厂类实现这个接口,最终由调用者通过工厂类创建对象。
更进一步:可以创建一个管理工厂类的工厂或者工具,方便使用者调用。
相比简单工厂只是讲产品抽象,工厂方法模式将工厂也抽象化了,不同的产品由不同的具体工厂负责生产。
优点:
修正了简单工厂模式中不遵守开放-封闭原则。工厂方法模式把选择判断移到了客户端去实现,如果想添加新功能就不用修改原来的类,直接修改客户端即可。
示例代码和类图:
#include <string>
#include <iostream>
using namespace std;
//实例基类,相当于 Product
class LeiFeng
{
public:
virtual void Sweep()
{
cout << "雷锋扫地" << endl;
}
};
//学雷锋的大学生,相当于 ConcreteProduct
class Student : public LeiFeng
{
public:
virtual void Sweep()
{
cout << "大学生扫地" << endl;
}
};
//学雷锋的志愿者,相当于 ConcreteProduct
class Volenter : 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 VolenterFactory : public LeiFengFactory {
public:
virtual LeiFeng* CreateLeiFeng()
{
return new Volenter();
}
};
//客户端
int main()
{
LeiFengFactory* sf = new LeiFengFactory();
LeiFeng* s = sf->CreateLeiFeng();
s->Sweep();
delete s;
delete sf;
return 0;
}
三、抽象工厂(Abstract Factory)模式
代码实现:一个接口文件中有多个接口(方法),每一个工厂类中也需要实现多个接口。
提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
工厂方法模式只能生产一类产品,而实际开发中我们需要的可能是一系列关联的产品对象,这就用到了抽象工厂模式。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
优点:
1.用户只需要知道具体工厂的名称就可得到所要的产品, 无须知道产品的具体创建过程;
2.灵活性增强, 对于新产品的创建,只需多写一个相应的工厂类。
应用场景:
用于交换产品系列,如,可以针对 Oracle、 MySQL、 DB2 等分别建立抽象工厂, 这样便于数据库之间的切换。
示例代码和类图:
#include <string>
#include <iostream>
#include <vector>
using namespace std;
//用户抽象接口
class IUser
{
public:
virtual void GetUser() = 0;
virtual void InsertUser() = 0;
};
//部门抽象接口
class IDepartment
{
public:
virtual void GetDepartment() = 0;
virtual void InsertDepartment() = 0;
};
//ACCESS 用户
class CAccessUser : public IUser
{
public:
virtual void GetUser()
{
cout << "Access GetUser" << endl;
}
virtual void InsertUser()
{
cout << "Access InsertUser" << endl;
}
};
//ACCESS 部门
class CAccessDepartment : public IDepartment
{
public:
virtual void GetDepartment()
{
cout << "Access GetDepartment" << endl;
}
virtual void InsertDepartment()
{
cout << "Access InsertDepartment" << endl;
}
};
//SQL 用户
class CSqlUser : public IUser
{
public:
virtual void GetUser()
{
cout << "Sql User" << endl;
}
virtual void InsertUser()
{
cout << "Sql User" << endl;
}
};
//SQL 部门类
class CSqlDepartment : public IDepartment
{
public:
virtual void GetDepartment()
{
cout << "sql getDepartment" << endl;
}
virtual void InsertDepartment()
{
cout << "sql insertdepartment" << endl;
}
};
//抽象工厂
class IFactory
{
public:
virtual IUser* CreateUser() = 0;
virtual IDepartment* CreateDepartment() = 0;
};
//ACCESS 工厂
class AccessFactory : public IFactory
{
public:
virtual IUser* CreateUser()
{
return new CAccessUser();
}
virtual IDepartment* CreateDepartment()
{
return new CAccessDepartment();
}
};
//SQL 工厂
class SqlFactory : public IFactory
{
public:
virtual IUser* CreateUser()
{
return new CSqlUser();
}
virtual IDepartment* CreateDepartment()
{
return new CSqlDepartment();
}
};
//客户端:
int main()
{
IFactory* factory = new SqlFactory();
IUser* user = factory-> CreateUser();
IDepartment* depart = factory-> CreateDepartment();
user-> GetUser();
depart-> GetDepartment();
return 0;
}