c++ 设计模式8 (Factory Method 工厂方法)
2016-02-23 22:13
931 查看
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之外(类比将变化赶到一个小范围),使其更加可控,从而使文件分割器的设计和使用满足面向对象设计原则,在应对变化时表现出优势。
模式定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使得一个类的实例化延迟(目的:解耦 ,手段:虚函数)到子类。
类图:
![](http://images2015.cnblogs.com/blog/793131/201602/793131-20160223221033802-774699627.png)
总结:
Factory Method模式用于隔离类对象的使用者与具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
Factory Method模式通过面向对象的手法,将所有创建的具体对象延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
Factory Method模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。
通过“对象创建”类模式绕开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之外(类比将变化赶到一个小范围),使其更加可控,从而使文件分割器的设计和使用满足面向对象设计原则,在应对变化时表现出优势。
//FileSpiltter1.cpp class ISplitter{ public: virtual void split()=0; virtual ~ISplitter(){} }; class BinarySplitter : public ISplitter{ }; class TxtSplitter: public ISplitter{ }; class PictureSplitter: public ISplitter{ }; class VideoSplitter: public ISplitter{ }; //MaiForm1.cpp class MainForm : public Form { TextBox* txtFilePath; TextBox* txtFileNumber; ProgressBar* progressBar; public: void Button1_Click(){ ISplitter * splitter= new BinarySplitter();//依赖具体类 splitter->split(); } };
//ISpiltterFactory.cpp //抽象类 class ISplitter{ public: virtual void split()=0; virtual ~ISplitter(){} }; //工厂基类 class SplitterFactory{ public: virtual ISplitter* CreateSplitter()=0; virtual ~SplitterFactory(){} }; //FileSpiltter2.cpp //具体类 class BinarySplitter : public ISplitter{ }; class TxtSplitter: public ISplitter{ }; class PictureSplitter: public ISplitter{ }; class VideoSplitter: public ISplitter{ }; //具体工厂 class BinarySplitterFactory: public SplitterFactory{ public: virtual ISplitter* CreateSplitter(){ return new BinarySplitter(); } }; class TxtSplitterFactory: public SplitterFactory{ public: virtual ISplitter* CreateSplitter(){ return new TxtSplitter(); } }; class PictureSplitterFactory: public SplitterFactory{ public: virtual ISplitter* CreateSplitter(){ return new PictureSplitter(); } }; class VideoSplitterFactory: public SplitterFactory{ public: virtual ISplitter* CreateSplitter(){ return new VideoSplitter(); } }; //MainForm2.cpp class MainForm : public Form { SplitterFactory* factory;//工厂 public: MainForm(SplitterFactory* factory){ this->factory=factory; } void Button1_Click(){ ISplitter * splitter= factory->CreateSplitter(); //多态new splitter->split(); } };
模式定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使得一个类的实例化延迟(目的:解耦 ,手段:虚函数)到子类。
类图:
![](http://images2015.cnblogs.com/blog/793131/201602/793131-20160223221033802-774699627.png)
总结:
Factory Method模式用于隔离类对象的使用者与具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
Factory Method模式通过面向对象的手法,将所有创建的具体对象延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
Factory Method模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。
相关文章推荐
- 58. Length of Last Word
- C/C++: 预处理指令
- C语言格式输入函数scanf()详解
- C语言笔记(2)
- C++面向对象编程<十>:虚函数与多态
- C++远航2
- C++学习笔记:继承
- C++2远征之离港篇
- neuq oj 1058: 谭浩强C语言(第三版)习题7.3 矩阵 C++
- c++ 头文件保护符
- C++模板类重载"<<"未定义错误
- 兔子问题 素数 水仙花数 三个经典C程序的解答 C知识回顾第一天
- CPP操作符重载
- A a和A *a = new A()区别
- C++编译器之间的不同性能
- 数组指针和指针数组
- C++基础知识面试30题
- C++链表的创建与操作
- C++面向对象编程<九>:面向对象-类之间的关系
- C语言实现某年某月某日是某年的第几天