c++ 设计模式8 (Factory Method 工厂方法)

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/yechanglv/p/6931011.html