好了,七月的第一篇博客正式標誌着我的迴歸。六月已經過去,七月還是新的!
GOF的書真的不好懂,不知道是我的原因還是我的原因?好吧,既然不懂只能參考csdn博客了:http://blog.csdn.net/u010064842/article/details/9150921
簡單抽象工廠模式
意圖:提供一個接口用來創建一系列相關或者相互依賴的對象,而無需指定它們具體的類。
設計模式的學習一定要配合例子。比如說我吃廚師做的食物這件事。食物有很多種,可能是紅燒肉,可能是清蒸魚,每一種特定的食物都是一個具體的類。但是我不需要指定具體的類,我只需要指定一個接口——食物,其中包含了每個具體的食物類的共同的fuction。然後我只要指定廚師類幫我做特定食物類表示的食物就行了。
例子見圖:
其實在上圖中,廚師就是Factory,食物就是Product。抽象爲抽象工廠模式見圖:
代碼實現:
//產品基類
#ifndef _PRODUCT_H
#define _PRODUCT_H
class Product
{
protected:
Product(){}
public:
virtual ~Product(){}
virtual void function() = 0;
};
#endif
//具體產品A
#ifndef _CONCRETE_PRODUCT_A_H
#define _CONCRETE_PRODUCT_A_H
#include "Product.h"
#include <iostream>
using namespace std;
class ConcreteProductA:public Product
{
public:
ConcreteProductA()
{
cout<<"創建產品A"<<endl;
}
virtual ~ConcreteProductA()
{
cout<<"釋放產品A"<<endl;
}
virtual void function()
{
cout<<"這是產品A的基本功能"<<endl;
}
};
#endif
//具體產品B
#ifndef _CONCRETE_PRODUCT_B_H
#define _CONCRETE_PRODUCT_B_H
#include "Product.h"
#include <iostream>
using namespace std;
class ConcreteProductB:public Product
{
public:
ConcreteProductB()
{
cout<<"創建產品B"<<endl;
}
virtual ~ConcreteProductB()
{
cout<<"釋放產品B"<<endl;
}
virtual void function()
{
cout<<"這是產品B的基本功能"<<endl;
}
};
#endif
//工廠類:負責具體產品的創建,有兩種方式實現產品的創建,
//I、創建不同的產品用不同的方法;II、創建不同產品用相同
//的方法,然後通過傳遞參數實現不同產品的創建。本實例中
//兩種模式都給出了,大家自行分析。
#ifndef _SIMPLE_FACTORY_H
#define _SIMPLE_FACTORY_H
#include "Product.h"
#include "ConcreteProductA.h"
#include "ConcreteProductB.h"
class SimpleFactory
{
public:
SimpleFactory(){}
~SimpleFactory(){}
Product *CreateProduct(int type)
{
Product *p = NULL;
switch(type)
{
case 0:
p = new ConcreteProductA();
break;
case 1:
p = new ConcreteProductB();
break;
default:
p = new ConcreteProductA();
break;
}
return p;
}
Product *CreateProductA()
{
Product *p = new ConcreteProductA();
return p;
}
Product *CreateProductB()
{
Product *p = new ConcreteProductB();
return p;
}
};
#endif
//客戶端程序
#include <iostream>
#include "SimpleFactory.h"
#include "Product.h"
using namespace std;
int main(int argc, char **argv)
{
SimpleFactory sf;
Product *p = sf.CreateProductA();
p->function();
delete p;
p = sf.CreateProduct(1);
p->function();
delete p;
system("pause");
return 0;
}
抽象工廠優點:將客戶與類相分離,客戶通過抽象接口操縱實例,產品的類名也在具體工廠的實現中被分離,不出現在客戶代碼中。
抽象工廠缺點:對修改不封閉,新增加產品您要修改工廠。違法了鼎鼎大名的開閉法則(OCP)。
抽象工廠模式的改進
在上面的代碼中,如果新出來一個ProductC,那我首先需要創建一個ConcreteProductC類,然後在SimpleFactory類中增加對ConcreteProductC的調用,這需要修改SimpleFactory類,使得這個類不能封閉。
改進方法:將廚師類抽象爲一個基類,再增加“做紅燒肉的廚師類”,“做清蒸魚的廚師類”等等,它們分別都繼承廚師這個基類。現在來看這個模式發生了變化,結構中多了一個廚師的抽象,抽象並不具體的加工產品了,至於是燉湯還是燉魚,是由這個抽象工廠的繼承子類來實現,現在的模式也就變成工廠方法模式了。這樣,如果我新出來一個菜,我不需要修改抽象的廚師類或者其他子類,我只需要增加一個做新菜的廚師類,繼承於抽象的廚師類,就可以方便的增加一個菜了。
圖示:
代碼實現:
在原來的基礎上增加:
//抽象的工廠類
#ifndef _FACTORY_H
#define _FACTORY_H
#include "Product.h"
class Factory
{
public:
Factory(){}
virtual ~Factory(){}
virtual Product* CreateProduct(int type=0) = 0;
};
#endif
//具體工廠類:工廠基類的具體實現,由此類決定創建具體產品。
//這裏ConcreteFactoryA 對於與圖中的工廠實現,ConcreteFactoryB
//對於與圖中的新工廠。
#ifndef _CONCRETE_FACTORY_A_H
#define _CONCRETE_FACTORY_A_H
#include "Factory.h"
class ConcreteFactoryA: public Factory
{
public:
ConcreteFactoryA(){}
virtual ~ConcreteFactoryA(){}
Product *CreateProduct(int type)
{
Product *p = NULL;
switch (type)
{
case 0:
p = new ConcreteProductA();
break;
case 1:
p = new ConcreteProductB();
break;
default:
p = new ConcreteProductA();
break;
}
return p;
}
};
#endif
//客戶端程序
#include <iostream>
#include "SimpleFactory.h"
#include "Product.h"
#include "Factory.h"
#include "ConcreteFactoryA.h"
#include "ConcreteFactoryB.h"
using namespace std;
int main(int argc, char **argv)
{
Factory *f = new ConcreteFactoryA();
Product *p = f->CreateProduct(0);
p->function();
delete p;
p = f->CreateProduct(1);
p->function();
delete p;
delete f;
f = new ConcreteFactoryB();
p = f->CreateProduct();
p->function();
delete p;
delete f;
system("pause");
return 0;
}
當然還可以繼續改進,不多說了,見圖: