整理自李建忠<C++设计模式>视频:https://www.bilibili.com/video/BV1kW411P7KS?p=8
一.导入:"对象创建"模式和工厂模式
工厂模式只是该模式下的一种.
二.举例说明
有这样一个场景:需要在MainForm中设计一个按钮,这个按钮具有文件分割的功能,支持多种类型的文件分割,比如二进制,文本类型.
不使用工厂模式的设计场景:
MainForm.cpp:
1 class MainForm 2 { 3 public: 4 MainForm() { 5 } 6 7 void Btn1Click() 8 { 15 ISplit *splitter = new BinarySplit(); 16 splitter->SplitFunc(); 18 } 19 };
Split.hpp
1 #pragma once 2 #include"stdio.h" 3 //抽象基类 4 class ISplit 5 { 6 public: 7 ISplit() {} 8 virtual ~ISplit() {} 9 10 virtual void SplitFunc() = 0; 11 }; 12 13 //具体类 14 class BinarySplit :public ISplit 15 { 16 public: 17 void SplitFunc() 18 { 19 printf("This is BinarySplit "); 20 } 21 }; 22 23 class TxtSplit : public ISplit 24 { 25 public: 26 void SplitFunc() 27 { 28 printf("This is TxtSplit "); 29 } 30 };
可以看到即便是Split.cpp中使用了多态的方法,在MainForm.cpp中的Btn1Click()还是会依赖于具体的类型,如果要实现别的类的切割函数,就需要在函数里添写,很不符合代码的复用性.
引入工厂模式后的场景:
Split.hpp保持不变
增加SplitFactory.hpp文件
1 #include"Split.hpp" 2 //工厂基类 3 class ISplitFactory 4 { 5 public: 6 ISplitFactory() { 7 8 } 9 virtual ~ISplitFactory() 10 { 11 12 } 13 14 virtual ISplit *CreateSplitter() = 0; 15 }; 16 17 //具体工厂 18 class BinarySplitFactory : public ISplitFactory 19 { 20 public: 21 ISplit *CreateSplitter() 22 { 23 return new BinarySplit(); 24 } 25 }; 26 27 class TxtSplitFactory : public ISplitFactory 28 { 29 public: 30 ISplit *CreateSplitter() 31 { 32 return new TxtSplit(); 33 } 34 };
修改MainForm.cpp文件.
#include"Split.hpp" #include"SplitFactory.hpp" class MainForm { public: ISplitFactory *splitFactory; MainForm(ISplitFactory *splitFactory) { this->splitFactory = splitFactory; } void Btn1Click() { ISplit *splitter = splitFactory->CreateSplitter();//通过工厂模式做成了"多态new" splitter->SplitFunc(); } };
这里增加的工厂基类同样定义了一个纯虚函数,用来创建Split对象,而实现的过程在子类中进行实现,这样的话就相当于延迟到子类.
上面的情况在MainForm.cpp中通过接受传递过来的splitFactory来确定运行时应该执行谁的函数.在这种模式下,对具体类型的依赖被放到了外边(main.cpp这个调用方)了,而上述代码里面不再存在依赖.
此时的main函数:
int main() { ISplitFactory *splitFactory = new BinarySplitFactory(); MainForm mf(splitFactory); mf.Btn1Click(); return 0; }
//注:这里没有考虑内存管理,正常应该在析构函数中delete掉堆上的内存
工厂模式那里,有些朋友疑惑为啥不直接传ISplitter就好了,同样是从外部传参,何必那么麻烦另外写个工厂?我觉得是因为如果直接传ISplitter,那这个方法只能用到这么一个ISplitter,而工厂却可以“批量生产”,这就是工厂的优势
--摘自https://www.bilibili.com/video/BV1kW411P7KS?p=8的切切切Y的评论.
三.结构总结
红色的部分是稳定的,蓝色的部分是变化的.让MainForm依赖红色的.