示例问题:
一个项目最初使用SQLServer数据库,后来根据项目情况要使用mysql数据库,此时需要更改所有和数据库有关的接口,工作量大,如果后期又要切换成PostgreSQL数据库,则所有和数据库有关的接口又要都改一遍。有没有方法能够在切换数据库的时候,不修改这么多接口?
分析:
可使用这个思路来解决:确定一个厂商的工厂,就可以确定所有物品都是来源于该厂商。比如要获取耐克的鞋、裤子、上衣、袜子等,则创建耐克这个厂商的工厂,然后从该工厂中取出来的鞋子,一定就是耐克的鞋子了。
解决方案:
AbstractFactory.h
该文件实现了用户数据基类(IUser)、部门数据基类(IDepartment)、工厂类基类(IFactory)。以及SQLServer用户数据类CSQLServerUser(继承IUser)、Mysql用户数据类CMysqlUser(继承IUser);SQLServer部门数据类CSQLServerDepartment(继承IDepartment)、Mysql部门数据类CMysqlDepartment(继承IDepartment);SQLServer工厂类CSQLServerFactory(继承IFactory)、Mysql工厂类CMysqlFactory(继承IFactory)。
调用工厂类CSQLServerFactory或者CMysqlFactory的CreateUser、CreateDepartment方法,则可创建针对不同数据库类型造作的对象。这样可以做到,当切换不同的数据库时,只需修改工厂类(继承IFactory的类)的创建即可。
#pragma once
#include <iostream>
//用户数据基类
class IUser
{
public:
IUser()
{
}
virtual ~IUser()
{
}
virtual void InsertUser() = 0;
virtual void GetUser() = 0;
};
//SQLServer用户数据类
class CSQLServerUser : public IUser
{
public:
CSQLServerUser()
{
}
virtual ~CSQLServerUser()
{
}
void InsertUser()
{
std::cout << "SQLServer数据库插入用户数据" << std::endl;
}
void GetUser()
{
std::cout << "SQLServer数据库取出用户数据" << std::endl;
}
};
//Mysql用户数据类
class CMysqlUser : public IUser
{
public:
CMysqlUser()
{
}
virtual ~CMysqlUser()
{
}
void InsertUser()
{
std::cout << "Mysql数据库插入用户数据" << std::endl;
}
void GetUser()
{
std::cout << "Mysql数据库取出用户数据" << std::endl;
}
};
//部分数据基类
class IDepartment
{
public:
IDepartment()
{
}
virtual ~IDepartment()
{
}
virtual void InsertDepartment() = 0;
virtual void GetDepartment() = 0;
};
//SQLServer部门数据类
class CSQLServerDepartment : public IDepartment
{
public:
CSQLServerDepartment()
{
}
virtual ~CSQLServerDepartment()
{
}
void InsertDepartment()
{
std::cout << "SQLServer数据库插入部门数据" << std::endl;
}
void GetDepartment()
{
std::cout << "SQLServer数据库取出部门数据" << std::endl;
}
};
//Mysql部门数据类
class CMysqlDepartment : public IDepartment
{
public:
CMysqlDepartment()
{
}
virtual ~CMysqlDepartment()
{
}
void InsertDepartment()
{
std::cout << "Mysql数据库插入部门数据" << std::endl;
}
void GetDepartment()
{
std::cout << "Mysql数据库取出部门数据" << std::endl;
}
};
//工厂基类
class IFactory
{
public:
IFactory()
: m_pUser(nullptr)
, m_pDepartment(nullptr)
{
}
virtual ~IFactory()
{
}
virtual IUser* CreateUser() = 0;
virtual IDepartment* CreateDepartment() = 0;
void DelUser()
{
if (nullptr != m_pUser)
{
delete m_pUser;
m_pUser = nullptr;
}
}
void DelDepartment()
{
if (nullptr != m_pDepartment)
{
delete m_pDepartment;
m_pDepartment = nullptr;
}
}
IUser* m_pUser;
IDepartment* m_pDepartment;
};
//SQLServer工厂类
class CSQLServerFactory : public IFactory
{
public:
CSQLServerFactory()
{
}
virtual ~CSQLServerFactory()
{
}
IUser* CreateUser()
{
m_pUser = new(std::nothrow) CSQLServerUser();
return m_pUser;
}
IDepartment* CreateDepartment()
{
m_pDepartment = new(std::nothrow) CSQLServerDepartment();
return m_pDepartment;
}
};
//Mysql工厂类
class CMysqlFactory : public IFactory
{
public:
CMysqlFactory()
{
}
virtual ~CMysqlFactory()
{
}
IUser* CreateUser()
{
m_pUser = new(std::nothrow) CMysqlUser();
return m_pUser;
}
IDepartment* CreateDepartment()
{
m_pDepartment = new(std::nothrow) CMysqlDepartment();
return m_pDepartment;
}
};
main.cpp
// main.cpp : Defines the entry point for the console application.
//
#include "AbstractFactory.h"
int main()
{
CSQLServerFactory SQLServerFactory;//SQLServer数据库工厂
IUser* pUserSQLServer = SQLServerFactory.CreateUser();//创建操作SQLServer数据库用户数据的对象指针
IDepartment* pDepartmentSQLServer = SQLServerFactory.CreateDepartment();//创建操作SQLServer数据部门数据的对象指针
pUserSQLServer->InsertUser();
pUserSQLServer->GetUser();
pDepartmentSQLServer->InsertDepartment();
pDepartmentSQLServer->GetDepartment();
SQLServerFactory.DelUser();
SQLServerFactory.DelDepartment();
CMysqlFactory MysqlFactory;//Mysql数据库工厂
IUser* pUserMysql = MysqlFactory.CreateUser();//创建操作mysql数据库用户数据的对象指针
IDepartment* pDepartmentMysql = MysqlFactory.CreateDepartment();//创建操作mysql数据部门数据的对象指针
pUserMysql->InsertUser();
pUserMysql->GetUser();
pDepartmentMysql->InsertDepartment();
pDepartmentMysql->GetDepartment();
MysqlFactory.DelUser();
MysqlFactory.DelDepartment();
system("pause");
return 0;
}
运行结果
抽象工厂模式解决的问题:
抽象工厂模式,提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体的类。
抽象工程模式的好处:
1. 易于切换产品系列。创建不同的工厂,即可切换所有产品;
2. 具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
返回目录:设计模式(C++实现)(总)