前文回顾
单例模式(一)
单例模式(二)
观察者模式
简单工厂模式
工厂方法模式(一)
工厂方法模式(二)
抽象工厂模式(一)
前言
在抽象工厂模式中,需要增加一个产品类时,需要同时增加好几个类,并且系列工厂类和客户端都得修改。可以使用简单工厂模式对抽象工厂进行改进。
实现举例
- 场景描述
假设一个简单的数据管理系统:有两个 Student (学生表)和 Grades(分数)两个对象表,一般对于一个对象表需要提供了对数据库操作(增、删、改、查)的类,然而在使用过程中数据库是可能进行更换的,比如 Access 切换到 Oracel。 - 产品类
①.Student 类
class Student
{
public:
Student(){}
};
②.Grades类
class Grades
{
public:
Grades(){}
};
- 数据库操作抽象基类
①.StudentHelper 类
#include "student.h"
class StudentHelper
{
public:
StudentHelper(){};
virtual void saveStudent(const Student &) = 0;
virtual Student getStudent(int id)= 0;
virtual ~StudentHelper() {}
};
②.GradesHelper 类
#include "grades.h"
class GradesHelper
{
public:
GradesHelper(){}
virtual void saveGrades(const Grades &) = 0;
virtual Grades getGrades(int id) = 0;
virtual ~GradesHelper(){}
};
- 数据库操作派生类
①.StudentHelperAccess 类
#include <iostream>
#include "studenthelper.h"
using namespace std;
class StudentHelperAccess : public StudentHelper
{
public:
StudentHelperAccess(){}
void saveStudent(const Student &) override
{
cout << "使用 Access 数据库保存一个 Student 对象"<<endl;
}
Student getStudent(int id) override
{
cout << "从 Access 数据库查询一个 Student 对象"<<endl;
}
static void * getStudentHelperAccess(){
return new StudentHelperAccess() ;
}
};
②.StudentHelperOracel 类
#include <iostream>
#include "studenthelper.h"
using namespace std;
class StudentHelperOracel : public StudentHelper
{
public:
StudentHelperOracel(){}
void saveStudent(const Student &) override
{
cout << "使用 Oracel 数据库保存一个 Student 对象"<<endl;
}
Student getStudent(int id) override
{
cout << "从 Oracel 数据库查询一个 Student 对象"<<endl;
}
static void* getStudentHelperOracel(){
return new StudentHelperOracel() ;
}
};
③.GradesHelperAccess 类
#include <iostream>
#include "gradeshelper.h"
using namespace std;
class GradesHelperAccess : public GradesHelper
{
public:
GradesHelperAccess(){}
void saveGrades(const Grades &) override
{
cout << "使用 Access 数据库保存一个 Grades 对象"<<endl;
}
Grades getGrades(int id) override
{
cout << "从 Access 数据库查询一个 Grades 对象"<<endl;
}
static void * getGradesHelperAccess(){
return new GradesHelperAccess() ;
}
};
④.GradesHelperOracel 类
#include <iostream>
#include "gradeshelper.h"
using namespace std;
class GradesHelperOracel : public GradesHelper
{
public:
GradesHelperOracel(){}
void saveGrades(const Grades &) override
{
cout << "使用 Oracel 数据库保存一个 Grades 对象"<<endl;
}
Grades getGrades(int id) override
{
cout << "从 Oracel 数据库查询一个 Grades 对象"<<endl;
}
static void * getGradesHelperOracel(){
return new GradesHelperOracel();
}
};
- 工厂类
#include "studenthelperaccess.h"
#include "studenthelperoracel.h"
#include "gradeshelperaccess.h"
#include "gradeshelperoracel.h"
#include <functional>
#include <map>
using namespace std;
class DataBaseHelper
{
public:
enum DBType{Access,Oracel};
enum DataType{StudentTable,GradesTable};
typedef function<void*()> Func;
public:
DataBaseHelper()
{
//产品注册
TableRegistry.insert(make_pair(make_pair(Access,StudentTable),StudentHelperAccess::getStudentHelperAccess));
TableRegistry.insert(make_pair(make_pair(Access,GradesTable),GradesHelperAccess::getGradesHelperAccess));
TableRegistry.insert(make_pair(make_pair(Oracel,StudentTable),StudentHelperOracel::getStudentHelperOracel));
TableRegistry.insert(make_pair(make_pair(Oracel,GradesTable),GradesHelperOracel::getGradesHelperOracel));
}
StudentHelper *createStudentHelper()
{
return static_cast<StudentHelper *>( TableRegistry[make_pair(currentDbtype,StudentTable)]());
}
GradesHelper *createGradesHelper()
{
return static_cast< GradesHelper *>( TableRegistry[make_pair(currentDbtype,GradesTable)]());
}
private:
map<pair<DBType,DataType>,Func> TableRegistry;
//当前的数据库类型,若需要切换数据库,仅需要修改这一出
DBType currentDbtype = Access;
};
- 客户端调用
#include "student.h"
#include "grades.h"
#include "databasehelper.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//创建工厂类,切换数据库无需修改客户端
DataBaseHelper *dbhelper = new DataBaseHelper ();
cout << "*****对 Student 的操作*****"<<endl;
Student student1;
StudentHelper * studenthelper = dbhelper->createStudentHelper();
studenthelper->saveStudent(student1);
studenthelper->getStudent(0);
cout << "*****对 Grades 的操作*****"<<endl;
Grades grades1;
GradesHelper * gradeshelper = dbhelper->createGradesHelper();
gradeshelper->saveGrades(grades1);
gradeshelper->getGrades(0);
delete gradeshelper;
delete studenthelper;
delete dbhelper;
return a.exec();
}