工廠方法(父類定義創建對象的接口,通過多態讓子類來創建具體的對象)

 

工廠方法的意圖

工廠方法主要用來創建對象,但是,具體創建什麼對象,由子類來實現,父類只是封裝一個虛創建對象的方法

抽象工廠的好處是在接口類中繞開的new的使用,避免因爲需求變化而頻繁的修改接口類,提高接口類的可複用性和可擴展性(易於維護),從而降低接口類對變化的依賴

 

舉例

我們在做文檔時,有時需要用Word,有時需要做PPT,還有時用Excel,所以,當我們創建不同類型的文件時,需要new不同的文檔對象,這時,爲了在不在接口或者基類中頻繁修改new的對象,就可以使用工廠方法設計模式

 

代碼如下

頭文件

products.h

#ifndef PRODUCTSHEADFILE
#define PRODUCTSHEADFILE

#include <iostream>
#include <cassert>

using namespace std;

class fileinstance//產品接口(基類)
{
public:
	fileinstance() {cout<<__func__<<endl;}
	virtual ~fileinstance(){cout<<__func__<<endl;}

	virtual void file()=0;
};

class word:public fileinstance//具體的產品
{
public:
	word(){cout<<__func__<<endl;}
	~word(){cout<<__func__<<endl;}

	virtual void file();
};

class ppt:public fileinstance//具體的產品
{
public:
	ppt(){cout<<__func__<<endl;}
	~ppt(){cout<<__func__<<endl;}

	virtual void file();
};

class excel:public fileinstance//具體的產品
{
public:
	excel(){cout<<__func__<<endl;}
	~excel(){cout<<__func__<<endl;}

	virtual void file();
};

#endif

factorymethod.h

#ifndef FACTORYHEADFILE
#define FACTORYHEADFILE

#include "products.h"

class creatfilefactory//工廠接口(基類)
{
public:
	creatfilefactory(){cout<<__func__<<endl;}
	virtual ~creatfilefactory(){cout<<__func__<<endl;}

	virtual fileinstance *creatfile()=0;//創建產品對象,返回抽象產品對象的指針,在子類中實現
};

class wordfactory:public creatfilefactory//具體文件的工廠
{
public:
	wordfactory(){cout<<__func__<<endl;}
	~wordfactory(){cout<<__func__<<endl;}

	virtual fileinstance *creatfile();
};

class pptfactory:public creatfilefactory//具體文件的工廠
{
public:
	pptfactory(){cout<<__func__<<endl;}
	~pptfactory(){cout<<__func__<<endl;}

	virtual fileinstance *creatfile();
};

class excelfactory:public creatfilefactory//具體文件的工廠
{
public:
	excelfactory(){cout<<__func__<<endl;}
	~excelfactory(){cout<<__func__<<endl;}

	virtual fileinstance *creatfile();
};

#endif

run.h

#ifndef RUNHEADFILE
#define RUNHEADFILE

#include "factorymethod.h"

class run
{
public:
	run(creatfilefactory *factory);//接受具體工廠的指針參數
	~run();
	void startrun();

private:
	creatfilefactory *m_factory;
};

#endif

源文件

products.cpp

products.cpp
#include "products.h"

void word::file()
{
	cout<<"word will be created"<<endl;
}

void ppt::file()
{
	cout<<"ppt will be created"<<endl;
}

void excel::file()
{
	cout<<"excel will be created"<<endl;
}

factorymethod.cpp

#include "factorymethod.h"

fileinstance *wordfactory::creatfile()
{
	return new word();
}

fileinstance *pptfactory::creatfile()
{
	return new ppt();
}

fileinstance *excelfactory::creatfile()
{
	return new excel();
}

run.cpp

#include "run.h"

run::run(creatfilefactory *factory)
{
	cout<<__func__<<endl;
	m_factory=factory;
}

run::~run()
{
	cout<<__func__<<endl;
	if (m_factory) {
		delete m_factory;
		m_factory=nullptr;
	}
}

void run::startrun()
{
	cout<<__func__<<endl;
	fileinstance *instance=m_factory->creatfile();//多態創建工廠
	instance->file();//多態生成文件
}

main.cpp

#include "run.h"

int main(int argc, char const *argv[])
{
	run r(new pptfactory());//將易變化的代碼(new pptfactory())限制在main函數中
	r.startrun();

	return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)  
project( dect_rect )  
INCLUDE_DIRECTORIES(include)
AUX_SOURCE_DIRECTORY(src DIR_SRCS)
add_executable(factorymethod ./src/products.cpp ./src/factorymethod.cpp ./src/run.cpp ./src/main.cpp)  

 

運行結果

如果要創建Word文件,只需要在main函數中修改r的參數,修改後重新編譯運行的結果如下

可以看到只編譯了main函數,而其他文件中的代碼並沒有參與編譯,這樣就降低了工廠基類和產品基類對變化部分(main)的依賴,提高了工廠基類和產品基類的模塊化程度(耦合性降低),而且工廠基類和產品基類的可複用性和擴展性也更高

 

參考:

https://www.bilibili.com/video/BV1kW411P7KS?p=8

《設計模式,可複用面向對象軟件的基礎》

 

歡迎大家評論交流,作者水平有限,如有錯誤,歡迎指出

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章