5. “对象创建”类模式
通过“对象创建”类模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。
5.1 工厂方法
动机:
在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?
代码示例:
仍然考虑文件分割器案例,不考虑与创建对象无关的代码部分,暂时忽略内存管理,专注于工厂方法模式的应用。
在实现代码1中,不同类型的文件分割器类(File,Pic,Video等)继承文件分割器抽象基类。
在MainForm中,MainForm类依赖(编译时依赖)了具体的类BinarySpitter,违背了依赖倒置原则。此时即出现了动机中说明的创建对象过程中导致的紧耦合。
采用工厂方法模式的解决方案见代码2,考虑过程如下:
1.利用new方法创建的对象必须依赖于具体类,不可取;所以考虑创建一个类,利用其中方法的返回值作为创建对象的结果;
2.然而单纯的返回一个具体类的对象仍然没有解决依赖倒置的问题,所以考虑将该类设计为一个抽象类,具体的返回由其子类来确定。
3.依照上述思想创建工厂基类SplitterFactory(抽象类),具体工厂(BinarySplitterFactory等)返回具体的对象。
4.MainForm使用过程中,声明一个工厂字段,在具体创建对象过程中采用统一的依赖于抽象的创建方法,即
ISplitter * splitter= factory->CreateSplitter(); //相当于多态new
而factory具体指向的对象类型由MainForm构造函数通过外界传入。
注:可以从上述分析和代码中看出,工厂方法模式的使用,并不是为了消除变化(事实上变化不可能消除),而是将变化排除在MainForm之外(类比将变化赶到一个小范围),使其更加可控,从而使文件分割器的设计和使用满足面向对象设计原则,在应对变化时表现出优势。
1 //FileSpiltter1.cpp
2 class ISplitter{
3 public:
4 virtual void split()=0;
5 virtual ~ISplitter(){}
6 };
7
8 class BinarySplitter : public ISplitter{
9
10 };
11
12 class TxtSplitter: public ISplitter{
13
14 };
15
16 class PictureSplitter: public ISplitter{
17
18 };
19
20 class VideoSplitter: public ISplitter{
21
22 };
23
24 //MaiForm1.cpp
25 class MainForm : public Form
26 {
27 TextBox* txtFilePath;
28 TextBox* txtFileNumber;
29 ProgressBar* progressBar;
30
31 public:
32 void Button1_Click(){
33
34
35
36 ISplitter * splitter=
37 new BinarySplitter();//依赖具体类
38
39 splitter->split();
40
41 }
42 };
1 //ISpiltterFactory.cpp
2
3 //抽象类
4 class ISplitter{
5 public:
6 virtual void split()=0;
7 virtual ~ISplitter(){}
8 };
9
10
11 //工厂基类
12 class SplitterFactory{
13 public:
14 virtual ISplitter* CreateSplitter()=0;
15 virtual ~SplitterFactory(){}
16 };
17
18 //FileSpiltter2.cpp
19
20 //具体类
21 class BinarySplitter : public ISplitter{
22
23 };
24
25 class TxtSplitter: public ISplitter{
26
27 };
28
29 class PictureSplitter: public ISplitter{
30
31 };
32
33 class VideoSplitter: public ISplitter{
34
35 };
36
37 //具体工厂
38 class BinarySplitterFactory: public SplitterFactory{
39 public:
40 virtual ISplitter* CreateSplitter(){
41 return new BinarySplitter();
42 }
43 };
44
45 class TxtSplitterFactory: public SplitterFactory{
46 public:
47 virtual ISplitter* CreateSplitter(){
48 return new TxtSplitter();
49 }
50 };
51
52 class PictureSplitterFactory: public SplitterFactory{
53 public:
54 virtual ISplitter* CreateSplitter(){
55 return new PictureSplitter();
56 }
57 };
58
59 class VideoSplitterFactory: public SplitterFactory{
60 public:
61 virtual ISplitter* CreateSplitter(){
62 return new VideoSplitter();
63 }
64 };
65
66 //MainForm2.cpp
67 class MainForm : public Form
68 {
69 SplitterFactory* factory;//工厂
70
71 public:
72
73 MainForm(SplitterFactory* factory){
74 this->factory=factory;
75 }
76
77 void Button1_Click(){
78
79
80 ISplitter * splitter=
81 factory->CreateSplitter(); //多态new
82
83 splitter->split();
84
85 }
86 };
模式定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使得一个类的实例化延迟(目的:解耦 ,手段:虚函数)到子类。
类图:
总结:
Factory Method模式用于隔离类对象的使用者与具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
Factory Method模式通过面向对象的手法,将所有创建的具体对象延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
Factory Method模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。
原文链接: https://www.cnblogs.com/wangxiaobao/p/5211414.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/229043
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!