我们思考C++设计模式 #4 观察者模式(Observer/Event)-CSDN博客中的文件分割的例子。对不同的文件我们可能有不同的分割策略。
class ISplitter {
public:
virtual void split() = 0;
virtual ~ISplitter(){}
};
class TxtSplitter:public ISplitter{
public:
void split(){
cout << "this is a txt splitter" << endl;
//...
}
};
class VideoSplitter:public ISplitter{
public:
void split(){
cout << "this is a video splitter" << endl;
//...
}
};
假设我们有一个button响应事件
void button_click(){
//...
ISplitter* txt_splitter = new TxtSplitter();
//ISplitter* pic_splitter = new PictureSplitter();
//ISplitter* video_splitter = new VideoSplitter();
txt_splitter->split();
//...
}
这样做虽然都是声明了一个虚基类的指针,但是还是依赖TxtSplitter这几个类的具体实现。也就是说我们这样不能绕开new的具体实现细节。
而且,如果我们的界面上只有一个与文件分割相关的按钮,就要在进行分割前进行大段的if-else判断,确定到底new哪个类型的文件分割器。这是一种相当低效且冗余的做法。
class SplitterFactory{
public:
virtual ISplitter* CreateSplitter() = 0;
virtual ~SplitterFactory() {}
};
class TxtSplitterFactory:public SplitterFactory{
public:
ISplitter* CreateSplitter(){
return new TxtSplitter();
}
};
class VideoSplitterFactory:public SplitterFactory{
public:
ISplitter* CreateSplitter(){
return new VideoSplitter();
}
};
我们创建一个工厂虚基类SplitterFactory,将创建(new)具体splitter类的方式放在其子类中去实现。
现在我们再看button_click中是如何调用的
void button_click(SplitterFactory* factory){
SplitterFactory* m_factory = factory;
ISplitter* splitter = m_factory->CreateSplitter();
splitter->split();
}
当然,m_factory这个工厂类的指针可以在button_click所属的类的成员变量中。调用buttoun_click时
TxtSplitterFactory* txtfactory = new TxtSplitterFactory();
VideoSplitterFactory* videofactory = new VideoSplitterFactory();
button_click(txtfactory);
button_click(videofactory);
以下是输出结果
8.工厂方法_哔哩哔哩_bilibili视频中是在button_click所属的类的构造函数中确定工厂指针,我个人感觉作为参数传递可能更容易理解。
工厂模式充分的利用了面向对象多态的性质,来保证了button_click函数中的稳定。
实际上,工厂模式并不能“消除”变化,而是将变化“驱赶”到了一处,也就是调用button_click之前。将变化集中起来处理,保证button与splitter之间结构的稳定。
理解C++多态对理解工厂模式很有必要。
目的:解耦
手段:虚函数