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;
}