2018-09-18 02:11:06
业务逻辑与数据访问的解耦:就是指利用多态的特性,使的程序在编译时并不知道具体要访问哪个数据,但是由于运行时多态的原因,它总能正确的访问数据。(参照工厂模式)
抽象工厂模式概述
抽象工厂模式(Abstract Factory),提供一个创建一系列先关或相互依赖对象的接口,而无需指定它们具体的类。 它和工厂模式的区别是,工厂模式一个具体的工厂它只有创建一个具体产品类的实例的能力。而抽象工厂的一个工厂则具备创建一些列相关或者相互依赖的类的实例,最佳应用是应用程序将可能面对的不同类型数据库的切换。
抽象工厂UML类图
抽象工厂模式的优点和缺点
抽象工厂的优点是:易于交换产品系列,由于具体工厂类,例如ConcreteFactory1只需要在应用程序初始化的时候出现一次,这就使得改变一个应用的具体工厂变的非常容易,它只需要改变具体工厂即可使用不同的产品配置。它让具体的创建实例过程与客户端分离,客户端是通过它们的出现接口操作实例,产品的具体类名也被具体工厂的实现分离不会出现在客户端代码中。
缺点:假设现在要新增一个产品,那么要做出如下改动,首先要新增抽象产品类AbstractProductC,接下来新增具体产品ConcreteProductC,然后问题来了,为了能够创建C这一个产品族系,你只能去修改目前已有的抽象工厂和具体工厂,具体做法就是增加一个方法AbstractProductC* createProductC();
代码实现
问题模型:有一个数据采集程序,数据有各种各样的来源,假设有A、B两家设备供应商,其中A提供了A1、A2两种种型号的设备,B提供了B1、B2两种种型号的设备,根据两个厂家提供的SDK,我们可以抽象出A1、A2的抽象产品类型AbstractProductA,B1、B2的抽象产品模型AbstractProductB。另外,假设今后可能会增添新的设备,为了日后面对新增需求高复用性和扩展性,我们使用抽象工厂模式来解决这个问题。(但这可能并不是最好的方式,考虑到产品内部数据类型变化时,你的产品类可能要进行修改,这就违背了对扩展开放,对修改关闭的设计原则)。
1.两个抽象产品类(虚基类)
#ifndef ABSTRACTPRODUCTA_H_ #define ABSTRACTPRODUCTA_H_ #include <string> class AbstractProductA { public: virtual bool login(const std::string &strUsername,const std::string &strPassword) = 0; virtual void setData(const int iData) = 0; virtual const int getData() const = 0; AbstractProductA() = default; virtual ~AbstractProductA() = default; protected: int m_iData{0}; std::string m_strUsername; std::string m_strPassword; }; #endif
#ifndef ABSTRACTPRODUCTB_H_ #define ABSTRACTPRODUCTB_H_ #include <string> class AbstractProductB { public: virtual void setConfig(const std::string& strCfg) = 0; virtual const std::string& receiveData() const =0; AbstractProductB() = default; virtual ~AbstractProductB() = default; protected: std::string m_strCfg; }; #endif
2.两个分别从AbstractProductA和AbstractProductB派生来的子类
#ifndef CONCRETEPRODUCTA1_H_ #define CONCRETEPRODUCTA1_H_ #include "AbstractProductA.h" class ConcreteProductA1:public AbstractProductA { public: bool login(const std::string &strUsername,const std::string &strPassword) override { m_strUsername = strUsername; m_strPassword = strPassword; return true; } void setData(const int iData) override { m_iData = iData; } const int getData() const override { return m_iData; } ConcreteProductA1() = default; ~ConcreteProductA1() = default; }; #endif
#ifndef CONCRETEPRODUCTB1_H_ #define CONCRETEPRODUCTB1_H_ #include "AbstractProductB.h" class ConcreteProductB1 : public AbstractProductB { public: void setConfig(const std::string &strCfg) { m_strCfg = strCfg; } const std::string& receiveData() const override { return m_strCfg; } ConcreteProductB1() = default; ~ConcreteProductB1() = default; }; #endif
3.一个抽象工厂类
#ifndef ABSTRACTFACTORY_H_ #define ABSTRACTFACTORY_H_ #include "AbstractProductA.h" #include "AbstractProductB.h" class AbstractFactory { public: virtual AbstractProductA* createProductA() =0; virtual AbstractProductB* createProductB() = 0; AbstractFactory() = default; virtual ~AbstractFactory() = default; }; #endif
4.一个从从抽象工厂派生来的子类
#ifndef CONCRETEFACTORY1_H_ #define CONCRETEFACTORY1_H_ #include "AbstractFactory.h" #include "AbstractProductA.h" #include "AbstractProductB.h" #include "ConcreteProductA1.h" #include "ConcreteProductB1.h" class ConcreteFactory1:public AbstractFactory { public: AbstractProductA* createProductA(); AbstractProductB* createProductB(); ConcreteFactory1() = default; ~ConcreteFactory1() = default; }; #endif #include "ConcreteFactory1.h" AbstractProductA* ConcreteFactory1::createProductA() { return new ConcreteProductA1; } AbstractProductB* ConcreteFactory1::createProductB() { return new ConcreteProductB1; }
5.main函数(客户端对这个抽象工厂的调用)
#include "ConcreteFactory1.h" #include <iostream> using namespace std; int main(int argc,char *argv[]) { ConcreteFactory1 objFactory1; auto *objProductA1 = objFactory1.createProductA(); objProductA1->setData(1); std::cout << objProductA1->getData() << std::endl; auto *objProductB1 = objFactory1.createProductB(); std::string strTest = "Hello World!"; objProductB1->setConfig(strTest); std::cout << objProductB1->receiveData() << std::endl; if(nullptr != objProductA1) { delete objProductA1; objProductA1 = nullptr; } if(nullptr != objProductB1) { delete objProductB1; objProductB1 = nullptr; } return(1); }
从main函数处入手,考虑需求增加时应该怎么处理,这样就能想到抽象工厂模式的不便之处了。在java语言里可以使用反射机制和简单工厂模式一起来对抽象工厂模式进行改进。