在界面类中要分割一个文件,文件分割器负责从主界面中获取path和要分割的分数。
//分割器 class BinarySplitter { public: ...void split() { cout << "开始文件分割..." << endl; } };
1 //界面类 2 class MainForm 3 { 4 public: 5 ... 6 void button_click() 7 { 8 //传入文件路径和分割的份数 9 FileSplitter *splitter = new FileSplitter(...); 10 //开始分割 11 splitter->split(); 12 } 13 }
面向接口编程告诉我们,一个对象的类型应该声明为抽象类,不应该是具体的类,如果声明的是具体类就说明不支持未来的变化(第9行)。所以要反过来判断是否有需求的变化。
如果文件分割器除了对二进制文件进行分割,还要对文本文件、图片文件、视频文件进行分割(他们内部的算法不一样)
1 //提起一个抽象基类 2 class ISplitter 3 { 4 public: 5 virtual void split() = 0; 6 virtual ~ISplitter(){} 7 8 }; 9 //二进制文件分割器 10 class BinarySplitter:public ISplitter 11 { 12 public: 13 14 void split() 15 { 16 cout << "二进制文件分割方法" << endl; 17 } 18 19 }; 20 //文本文件分割器 21 class TxtSplitter:public BinarySplitter 22 { 23 public: 24 25 void split() 26 { 27 cout << "文本文件分割方法" << endl; 28 } 29 30 }; 31 //图片文件分割器 32 class PictureSplitter:public BinarySplitter 33 { 34 public: 35 36 void split() 37 { 38 cout << "图片文件分割方法" << endl; 39 } 40 41 }; 42 //视频文件分割器 43 class VideoSplitter:public BinarySplitter 44 { 45 public: 46 47 void split() 48 { 49 cout << "视频文件分割方法" << endl; 50 } 51 52 };
根据依赖导致原则:依赖(编译时依赖)抽象(稳定)不应该依赖实现细节(不稳定),也是面向接口编程的思想,将界面类中第9行修改如下:
ISplitter *splitter = new BinarySplitter(...);
splitter是一个抽象类型,但是new 后面是一个具体类型,所以这行代码依旧是一个细节依赖,不符合依赖倒置原则。这就是工厂方法模式需要解决的问题。需要绕开new,因为new带来的是细节依赖。也是面向接口编程的一个必然需求。
怎么绕开new来创建一个对象?无论是在堆上还在栈上都需要依赖具体的类。
可以通过一个方法来返回一个对象。
//添加一个抽象工厂 class SplitterFactory { public: virtual ISplitter * CreatSplitter() = 0; virtual ~SplitterFactory(){} }; //每一种分割器对应一个具体工厂 class BinarySplitterFactory :public SplitterFactory { public: virtual ISplitter * CreatSplitter() { return new BinarySplitter; } }; class TxtSplitterFactory :public SplitterFactory { public: virtual ISplitter * CreatSplitter() { return new TxtSplitter; } }; class PictureSplitterFactory :public SplitterFactory { public: virtual ISplitter * CreatSplitter() { return new PictureSplitter; } }; class VideoSplitterFactory :public SplitterFactory { public: virtual ISplitter * CreatSplitter() { return new VideoSplitter; } };
修改一下界面类
//界面类 class MainForm { public: SpliiterFactory *m_factory; //从外界传入一个具体的工厂 MainForm(SpliiterFactory *factory):m_factory(factory){} void button_click() { //通过工厂创建对象,绕开new,实现依赖抽象 FileSplitter *splitter = factory->CreatSplitter(); //多态new splitter->split(); } ... }
最后在分析一下工厂方法的定义:定义一个用于创建对象的接口(SplitterFactory类中的虚函数CreatSplitter),让子类(具体的工厂)决定实例化哪一个类。目的是为了解耦,解new和具体类之间的耦合。
结构图