工厂方法的意图
工厂方法主要用来创建对象,但是,具体创建什么对象,由子类来实现,父类只是封装一个虚创建对象的方法
抽象工厂的好处是在接口类中绕开的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
《设计模式,可复用面向对象软件的基础》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出