1 核心思想
抽象工厂模式,提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。
抽象工厂包含了一个接口AbstractFactory,所有的具体工厂都需要实现该接口,这个接口包含一组方法来生产产品。
具体工厂ConcreteFactory1和ConcreteFactory2实现不同的产品家族。要创建一个产品,客户只需要使用其中的一个工厂而完全不需实例化任何产品对象。
AbstractProductA和AbstractProductB是产品家族,每个具体工厂都可以生产一整组的产品。
客户端代码中只需涉及抽象工厂,运行时将自动使用实际的工厂。
2 抽象工厂的优缺点
优点:
- 最大的好处是便于交换产品系列,由于具体的工厂类只在应用的初始化中出现一次,这使得改变一个应用的具体工厂变得十分容易,只需要改变具体工厂即可使用不同的产品配置;
- 它让具体的创建实例过程与客户端相分离,客户端是通过抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。
缺点:
在扩充给具体工厂的产品组时,需要修改AbstractFactory、ConcreteFactory1和ConcreteFactory2三个类,分别添加新产品的创建函数,违背了开闭原则。
3 简单工厂、工厂方法和抽象工厂的关系
相同点:
所有的工厂模式(简单工厂、工厂方法、抽象工厂)都是为了封装产品的创建过程;
所有的工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合;
不同点:
简单工厂将产品的创建过程封装成类或者函数,将客户程序从具体类解耦;
工厂方法使用继承,把对象的创建委托给子类,子类实现工厂方法来创建对象;
抽象工厂使用对象组合,对象的创建被实现在工厂接口所暴出来的方法中。
依赖关系:
抽象工厂中每一个创建产品的方法(CreateProductA和CreateProductB)都是使用工厂方法模式进行实现的。
4 抽象工厂示例代码
两个具体工厂,分别是SqlServerFactory和AccessFactory;两个产品组,分别是User和Department。
使用抽象工厂模式,如果项目需要将数据库从SqlServer变更成Access,只需将main函数中的AbsFactory* pFac = new SqlServerFactory变为AbsFactory* pFac = new AccessFactory即可。
//AbsFactory.h
#pragma once
#include "User.h"
#include "Department.h"
class AbsFactory
{
public:
AbsFactory() {};
virtual ~AbsFactory() {};
virtual User* CreateUser() = 0;
virtual Department* CreateDepartment() = 0;
};
class SqlServerFactory :public AbsFactory
{
public:
SqlServerFactory() {};
~SqlServerFactory() {};
User* CreateUser();
Department* CreateDepartment();
};
class AccessFactory :public AbsFactory
{
public:
AccessFactory() {};
~AccessFactory() {};
User* CreateUser();
Department* CreateDepartment();
};
//AbsFactory.cpp
#include "AbsFactory.h"
User* SqlServerFactory::CreateUser()
{
return new SqlServerUser;
}
Department* SqlServerFactory::CreateDepartment()
{
return new SqlServerDepartment;
}
User* AccessFactory::CreateUser()
{
return new AccessUser;
}
Department* AccessFactory::CreateDepartment()
{
return new AccessDepartment;
}
//User.h
#pragma once
#include<iostream>
class User
{
public:
User() {};
virtual ~User() {};
virtual void Insert(User* pOneUser) = 0;
virtual User* GetUser(int nID) = 0;
};
class SqlServerUser :public User
{
public:
SqlServerUser() {};
~SqlServerUser() {};
void Insert(User* pOneUser);
User* GetUser(int nID);
};
class AccessUser :public User
{
public:
AccessUser() {};
~AccessUser() {};
void Insert(User* pOneUser);
User* GetUser(int nID);
};
//User.cpp
#include "User.h"
void SqlServerUser::Insert(User* pOneUser)
{
std::cout << "在Sql Server中给User表插入一条记录" << std::endl;
}
User* SqlServerUser::GetUser(int nID)
{
std::cout << "在Sql Server的User表中根据ID获取一条记录" << std::endl;
return nullptr;
}
void AccessUser::Insert(User* pOneUser)
{
std::cout << "在Access中给User表插入一条记录" << std::endl;
}
User* AccessUser::GetUser(int nID)
{
std::cout << "在Access的User表中根据ID获取一条记录" << std::endl;
return nullptr;
}
//Department.h
#pragma once
#include <iostream>
class Department
{
public:
Department() {};
virtual ~Department() {};
virtual void Insert(Department* pOneDepartment) = 0;
virtual Department* GetDepartment(int nID) = 0;
};
class SqlServerDepartment :public Department
{
public:
SqlServerDepartment() {};
~SqlServerDepartment() {};
void Insert(Department* pOneDepartment);
Department* GetDepartment(int nID);
};
class AccessDepartment :public Department
{
public:
AccessDepartment() {};
~AccessDepartment() {};
void Insert(Department* pOneDepartment);
Department* GetDepartment(int nID);
};
//Department.cpp
#include "Department.h"
void SqlServerDepartment::Insert(Department* pOneDepartment)
{
std::cout << "在Sql Server中给Department表插入一条记录" << std::endl;
}
Department* SqlServerDepartment::GetDepartment(int nID)
{
std::cout << "在Sql Server的Department表中根据ID获取一条记录" << std::endl;
return nullptr;
}
void AccessDepartment::Insert(Department* pOneDepartment)
{
std::cout << "在Access中给Department表插入一条记录" << std::endl;
}
Department* AccessDepartment::GetDepartment(int nID)
{
std::cout << "在Access的Department表中根据ID获取一条记录" << std::endl;
return nullptr;
}
//main.cpp
#include "AbsFactory.h"
#include "User.h"
#include "Department.h"
int main()
{
AbsFactory* pFac = new AccessFactory;
User* pUser = pFac->CreateUser();
User* temp = nullptr;
pUser->Insert(temp);
pUser->GetUser(0);
Department* pDep = pFac->CreateDepartment();
Department* tmp = nullptr;
pDep->Insert(tmp);
pDep->GetDepartment(0);
return 0;
}
执行结果: