抽象工厂就是提供一个创建一系列相关或者相互依赖对象的接口,具体就是下面的表示,假如数据库有两个表user和department两个表的有相同的操作,比如有insert和get,接口一样但是操作所需要的数据,和所访问的表不一样,而且还可能这两个表会在不同的数据库中存储,比如access和sqlserver,因此我们把不同的表作为基类,根据不同的数据库来派生出不同的派生类,这样就可以隐藏不同数据库的操作细节差异,只需知道表的操作接口即可,然后实现一个工厂类,首先有一个工厂基类作为抽象,根据不同的数据库类型派生出不同的工厂类,每一个工厂类进生产特定数据库的表(这里假设两个表在同一种数据库中)。和工厂模式的区别,工厂模式只能创建一个类,抽象工厂可以创建一系列相关的类。
下面实现了抽象工厂模式,这里有两个表 user、department,还可能有两种不同的数据库access、sqlserver,因此使用抽象工厂模式,具体详情看下述代码。
这个设计模式有以下一个部分:
#include <iostream>
using namespace std;
class user
{
public:
int id;
string name;
};
class iUser
{
public:
virtual void insert(user *use) = 0;
virtual user *getUser(int id) = 0;
};
class sqlserverUser : public iUser
{
public:
virtual void insert(user *use)
{
cout<<"在SQL server 中给user表添加一条记录\n";
}
virtual user * getUser(int id)
{
cout<<"在SQL server 中根据id在user表得到一条记录\n";
return nullptr;
}
};
class accessUser : public iUser
{
public:
virtual void insert(user *use)
{
cout<<"在Access 中给user表添加一条记录\n";
}
virtual user * getUser(int id)
{
cout<<"Access 中根据id给user表得到一条记录\n";
return nullptr;
}
};
class iDepartment
{
public:
virtual void insert(string department) = 0;
virtual string getDepartment(int fd) = 0;
};
class sqlserverDepartment : public iDepartment
{
public:
virtual void insert(string department)
{
cout<<"在SQL server中给department表中添加了一条记录\n";
}
virtual string getDepartment(int fd)
{
cout<<"在SQL server中根据department得到一条department表的记录\n";
return "";
}
};
class accessDepartment : public iDepartment
{
public:
virtual void insert(string department)
{
cout<<"在Access中给department表中添加了一条记录\n";
}
virtual string getDepartment(int fd)
{
cout<<"在Access中根据id得到一条department表的记录\n";
return "";
}
};
class iFactory
{
public:
virtual iUser *creatUser() = 0;
virtual iDepartment *creatDepartment() = 0;
};
class sqlserverFactory : public iFactory
{
virtual iUser *creatUser(){return new sqlserverUser();};
virtual iDepartment *creatDepartment(){return new sqlserverDepartment();};
};
class accessFactory : public iFactory
{
virtual iUser *creatUser(){return new accessUser();};
virtual iDepartment *creatDepartment(){return new accessDepartment();};
};
int main()
{
user *use = new user();
use->id = 1;
use->name = "wqwq";
string dept = "";
iFactory *factory = new accessFactory();
iUser *iu = factory->creatUser();
iu->insert(use);
iu->getUser(1);
iDepartment *id = factory->creatDepartment();
id->insert(dept);
id->getDepartment(1);
delete use;
delete factory;
delete iu;
delete id;
return 0;
}
可以创建一系列相关的类,自己就不需要考虑这些类之间的关系,直接由抽象工厂来帮创建即可,若是适应工厂模式,那么根据不同的表和不同的数据库,会有很多种组合,这样的话就会把不同数据库这一细节暴露给了用户,违反了最小知道原则。
当需要更改不用的数据库类型的时候,只需要把工厂类的具体类更换为不同的派生类即可,其他类不需要修改,客户端可以直接使用抽象表的接口,具体的类名不会暴露给客户端
当需要新添加表的时候需要增加很多类(还好了,对添加开放,对修改封闭),并且需要更改抽象工厂类(因为抽象工厂要生成一系列的类,那么添加新表的时候,需要改抽象工厂类)
由于派生的工厂类就是创建对应数据库的表对象,因此可以使用简单工厂模式来创建,根据参数生成不同的对象。java中有反射这个东西。
1、迪米特原则(最小知道原则)
这个应该可以能看出,用户仅知道表的接口,内部的数据库类型完全不知情。
2、单一职责
每个工厂类仅负责一种数据库的表的创建,概不负责其他类型数据库,一个表类仅复杂一个表的操作,概不负责其他表的操作。