工廠方法的意圖
工廠方法主要用來創建對象,但是,具體創建什麼對象,由子類來實現,父類只是封裝一個虛創建對象的方法
抽象工廠的好處是在接口類中繞開的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
《設計模式,可複用面向對象軟件的基礎》
歡迎大家評論交流,作者水平有限,如有錯誤,歡迎指出