3.1 抽象工廠

好了,七月的第一篇博客正式標誌着我的迴歸。六月已經過去,七月還是新的!

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

當然還可以繼續改進,不多說了,見圖:



發佈了29 篇原創文章 · 獲贊 46 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章