模式定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method
使得一个类的实例化延迟(目的:解耦合,手段:虚函数)到子类中去。
我们还是来看一个实际例子:
例如我们要设计一个文件分割的程序,我们在主窗口中点击按钮,实现文件分割的功能。但是我们要分割的文件可能是文本文件,也可能是二进制文件,也可能是视频文件等等,那么我们最初写下的代码就可能像下面一样:
MainForm
类:
class MainForm : public Form
{
TextBox* txtFilePath;
TextBox* txtFileNumber;
ProgressBar* progressBar;
public:
void Button1_Click(){
ISplitter * splitter=
new BinarySplitter();//依赖具体类 定死了
splitter->split();
}
};
FileSplitter
类:
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{
};
根据依赖倒置原则:我们应该尽量依赖抽象类,而不是具体实现,可以发现:在MainForm
类中,splitter
的实现已经被绑定为具体的类,那么如果我要添加分割其他文件的功能就不得不修改或者增加此处的源码,而且这里只是一个简化的例子,如果项目中多处要使用这样的splitter
,那么就有可能需要在多处进行修改。
所以我们引入工厂类,工厂类负责创建类对象。
我们将各个分割器提升到抽象基类。
ISplitterFactory
的实现:
//抽象类
class ISplitter{
public:
virtual void split()=0;
virtual ~ISplitter(){}
};
//工厂基类
class SplitterFactory{
public:
virtual ISplitter* CreateSplitter()=0;
virtual ~SplitterFactory(){}
};
那么MainForm
的实现就变成如下:
class MainForm : public Form
{
SplitterFactory* factory;//工厂
public:
MainForm(SplitterFactory* factory){
this->factory=factory;
}
void Button1_Click(){
ISplitter * splitter=
factory->CreateSplitter(); //多态new
splitter->split();
}
};
而FileSplitter2
的实现如下:
//具体类
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();
}
};
可以发现,我们实现了一个分割器的抽象基类,并且实现了分割器抽象基类对应的工厂类,而实际分割器只要继承自抽象基类,并且实现出自己的分割器就可以了。(增加几个源文件),而MainForm
此时也只依赖与抽象的工厂基类,而与具体的分割器不是耦合的了。
结构: