工厂方法-Factory Method
动机-Motivation
在软件系统中,经常面临创建对象的工作,由于需求的变化,需要创建的对象的具体类型也经常变化。
例子
文件分割器
代码
class ISplitter{
public:
virtual void split()=0;
virtual ~ISplitter(){}
};
class BinarySplitter : public ISplitter{
};
class TxtSplitter: public ISplitter{
};
class PictureSplitter: public ISplitter{
};
class VideoSplitter: public ISplitter{
};
class MainForm : public Form
{
TextBox* txtFilePath;
TextBox* txtFileNumber;
ProgressBar* progressBar;
public:
void Button1_Click(){
ISplitter * splitter=
new BinarySplitter();//依赖具体类
splitter->split();
}
};
为了支持多种的文件分割方式,写出一个抽象基类ISplitter,提供分割接口。同时让各类格式下的分割如文本格式分割下文件分割、图片格式下的文件分割、视频格式下的文件分割等继承自ISplitter,实现不同的分割方式。
但在具体使用时,任然需要细节依赖(如new BinarySplitter()),依赖具体类,违背依赖倒置原则。
考虑重构代码,使用某种方法去返回一个对象,来避免对象创建时对细节的依赖。
创建一个SplitterFactory类,定义一个方法,返回类型为ISplitter,return 具体类(如new BinarySplitter())。
但此时的工厂类依赖具体实现,而MainForm依赖工厂,最后MainFrom仍然依赖于具体实现。
考虑改变工厂创建函数,使该函数成为一个pure Virtual函数,延迟需求至运行时。所以可以不必提供具体实现,避免编译时依赖。
MainForm需要使用工厂类指针(通常放在类内作数据成员,通过构造器赋值),通过该指针去创建类型。创建具体实现的工厂类去继承抽象工厂,去实现各类的创建函数,返回对应类型的对象。
每一个具体类,都有一个对应的具体工厂,去继承抽象工厂,来完成对象创建工作。
让MainForm依赖工厂基类,而不是依赖具体类,可以实现MainForm的独立编译。
版本2
//具体类
class BinarySplitter : public ISplitter{
};
class TxtSplitter: public ISplitter{
};
class PictureSplitter: public ISplitter{
};
class VideoSplitter: public ISplitter{
};
//具体工厂
class BinarySplitterFactory: public SplitterFactory{
public:
virtual ISplitter* CreateSplitter(){
return new BinarySplitter();
}
};
class TxtSplitterFactory: public SplitterFactory{
public:
virtual ISplitter* CreateSplitter(){
return new TxtSplitter();
}
};
class PictureSplitterFactory: public SplitterFactory{
public:
virtual ISplitter* CreateSplitter(){
return new PictureSplitter();
}
};
class VideoSplitterFactory: public SplitterFactory{
public:
virtual ISplitter* CreateSplitter(){
return new VideoSplitter();
}
};
//抽象类
class ISplitter{
public:
virtual void split()=0;
virtual ~ISplitter(){}
};
//工厂基类
class SplitterFactory{
public:
virtual ISplitter* CreateSplitter()=0;
virtual ~SplitterFactory(){}
};
class MainForm : public Form
{
SplitterFactory* factory;//工厂
public:
MainForm(SplitterFactory* factory){
this->factory=factory;
}
void Button1_Click(){
ISplitter * splitter=
factory->CreateSplitter(); //多态new
splitter->split();
}
};
总结
定义一个用于创建对象的接口,让子类去实现如何创建对象。
让子类的对象的创建从编译时延迟至运行时,将紧耦合(需要具体类创建)变为松耦合(未来创建对象类)。
变化始终存在,只是做了隔离。
当新的需求发生时(另一种文件分割方式),MainForm的多态new不需要变动,继续让新的具体类继承ISplitter抽象类,并创建对应类的工厂继承工厂基类,实现创建对象方法。