Linux C++ 045-设计模式之工厂模式
本节关键字:Linux、C++、设计模式、简单工厂模式、工厂方法模式、抽象工厂模式
相关库函数:
简单工厂模式
基本简介
从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
实现方式
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
角色结构
工厂角色:简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
抽象产品角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品角色:是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。
class SimpleOperation
{
public:SimpleOperation() {numberA = 1;numberB = 1;}
public:double numberA, numberB;virtual double getResult() = 0;
};class AddSimpleOperation : public SimpleOperation
{double getResult() {return numberA + numberB;}
};
class SubSimpleOperation : public SimpleOperation
{double getResult() {return numberA - numberB;}
};
class MulSimpleOperation : public SimpleOperation
{double getResult() {return numberA * numberB;}
};
class DivSimpleOperation : public SimpleOperation
{double getResult() {return numberA / numberB;}
};
class OperSimpleOperation
{
public:static SimpleOperation* createOperation(char c){switch (c){case '+':return new AddSimpleOperation;break;case '-':return new SubSimpleOperation;break;case '*':return new MulSimpleOperation;break;case '/':return new DivSimpleOperation;break;}}
};
int main_SimpleFactory()
{OperationSimple* oper = operFactorySimple::createOperation('+');oper->numberA = 123;oper->numberB = 456;cout << oper->getResult() << endl;return 0;
}
工厂方法模式
基本简介
工厂方法(FactoryMethod)模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”
在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不接触哪一个产品类被实例化这种细节。这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
在Factory Method模式中,工厂类与产品类往往具有平行的等级结构,它们之间一一对应。
实现方式
工厂方法模式的实质是:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。
角色结构
抽象工厂(Creator)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
class OperationMethod
{
public:OperationMethod() {}~OperationMethod() {}
public:double numberA, numberB;virtual double getResult() = 0;
};
class AddOperationMethod : public OperationMethod
{double getResult() {return numberA + numberB;}
};
class SubOperationMethod : public OperationMethod
{double getResult() {return numberA - numberB;}
};
class MulOperationMethod : public OperationMethod
{double getResult() {return numberA * numberB;}
};
class DivOperationMethod : public OperationMethod
{double getResult() {return numberA / numberB;}
};
class IFactoryMethod
{
public:virtual OperationMethod* createOperation() = 0;
};
class AddFactoryMethod : public IFactoryMethod
{
public:static OperationMethod* createOperation() {return new AddOperationMethod();}
};
class SubFactoryMethod : public IFactoryMethod
{
public:static OperationMethod* createOperation() {return new SubOperationMethod();}
};
class MulFactoryMethod : public IFactoryMethod
{
public:static OperationMethod* createOperation() {return new MulOperationMethod();}
};
class DivFactoryMethod : public IFactoryMethod
{
public:static OperationMethod* createOperation() {return new DivOperationMethod();}
};
int main_MethodFactory()
{OperationMethod* oper = MulFactoryMethod::createOperation();oper->numberA = 666;oper->numberB = 999;cout << oper->getResult() << endl;return 0;
}
抽象工厂模式
基本简介
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品角色都有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结构。
实现方式
根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
产品族
产品族是指位于不同产品等级结构中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。显然,每一个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。叫做相图。
当有多个不同的等级结构的产品时,如果使用工厂方法模式就势必要使用多个独立的工厂等级结构来对付这些产品的等级结构。如果这些产品等级结构是平行的,会导致多个平行的工厂等级结构。
抽象工厂模式使用同一个 工厂等级结构负责这些不同产品等级结构产品对象的创建。
对于每一个产品族,都有一个具体工厂。而每一个具体工厂创建属于同一个产品族,但是分属于不同等级结构的产品。
通过引进抽象工厂模式,可以处理具有相同(或者相似)等级结构的多个产品族中的产品对象的创建问题。
由于每个具体工厂角色都需要负责两个不同等级结构的产品对象的创建,因此每个工厂角色都需要提供两个工厂方法,分别用于创建两个等级结构的产品。既然每个具体工厂角色都需要实现这两个工厂方法,所以具有一般性,不妨抽象出来,移动到抽象工厂角色中加以声明。
class IUser
{
public:virtual void getUser() = 0;virtual void setUser() = 0;
};
class SqlUser : public IUser
{
public:void getUser() {cout << "在sql中返回user" << endl;}void setUser() {cout << "在sql中设置user" << endl;}
};
class AccessUser : public IUser
{
public:void getUser() {cout << "在Access中返回user" << endl;}void setUser() {cout << "在Access中设置user" << endl;}
};
class IDepartment
{
public:virtual void getDepartment() = 0;virtual void setDepartment() = 0;
};
class SqlDepartment : public IDepartment
{
public:void getDepartment() {cout << "在sql中返回Department" << endl;}void setDepartment() {cout << "在sql中设置Department" << endl;}
};
class AccessDepartment : public IDepartment
{
public:void getDepartment() {cout << "在Access中返回Department" << endl;}void setDepartment() {cout << "在Access中设置Department" << endl;}
};
class IFactory
{
public:virtual IUser* createUser() = 0;virtual IDepartment* createDepartment() = 0;
};
class SqlFactory : public IFactory
{
public:IUser* createUser() {return new SqlUser();}IDepartment* createDepartment() {return new SqlDepartment();}
};
class AccessFactory :public IFactory
{
public:IUser* createUser() {return new AccessUser();}IDepartment* createDepartment() {return new AccessDepartment();}
};
class DataAccess // 简单工厂类
{
private:static string db;
public:static IUser* createUser() {if (db == "access") {return new AccessUser();}else if (db == "sql") {return new SqlUser();}}static IDepartment* createDeparment() {if (db == "access") {return new AccessDepartment();}else if (db == "sql") {return new SqlDepartment();}}
};
string DataAccess::db = "sql";int main_AbstractFactory()
{// IFactory* factory = new SqlFactory();IFactory* factory;IUser* user;IDepartment* department;factory = new AccessFactory();user = factory->createUser();department = factory->createDepartment();user->getUser();user->setUser();department->getDepartment();department->setDepartment();// 简单工厂类的调用user = DataAccess::createUser();department = DataAccess::createDeparment();user->getUser();user->setUser();department->getDepartment();department->setDepartment();return 0;
}