创建型设计模式之工厂方法模式:
一、含义
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
通俗来说就是,使用工厂类来创建产品类(传入不同的实现类(类名或其标识)返回相应的对象)
二、代码说明
1.主要有两个角色
1)产品类
表示产品
2)创建类(工厂类)
负责创建产品类
2.在用C实现过程中也是参考这种思想,以进生产超人举例,具体实现如下:
1)工厂方法模式使用场景:
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : FactoryMethodPatternUsage.c 5 * Description : 工厂方法模式的使用 6 7 book@book-desktop:/work/projects/test/DesignPatterns/FactoryMethodPattern$ gcc -o FactoryMethodPatternUsage AdultSuperMan.c ChildSuperMan.c FactoryMethodPattern.c FactoryMethodPatternUsage.c 8 book@book-desktop:/work/projects/test/DesignPatterns/FactoryMethodPattern$ ./FactoryMethodPatternUsage 9 ------------生产成年超人:------------ 10 超人力大无穷 11 -----------生产未成年超人:----------- 12 小超人的能力是刀枪不入,快速运动 13 14 * Created : 2017.07.31. 15 * Author : Yu Weifeng 16 * Function List : 17 * Last Modified : 18 * History : 19 ******************************************************************************/ 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include "FactoryMethodPattern.h" 24 25 26 27 28 /***************************************************************************** 29 -Fuction : main 30 -Description : 31 -Input : 32 -Output : 33 -Return : 34 * Modify Date Version Author Modification 35 * ----------------------------------------------- 36 * 2017/07/31 V1.0.0 Yu Weifeng Created 37 ******************************************************************************/ 38 int main(int argc,char **argv) 39 { 40 T_SuperManFactory tSuperManFactory=newSuperManFactory; 41 T_SuperMan tSuperMan; 42 printf("------------生产成年超人:------------ "); 43 tSuperMan=tSuperManFactory.CreatSuperMan("adult"); 44 tSuperMan.SuperManTalent(); 45 printf("-----------生产未成年超人:----------- "); 46 tSuperMan=tSuperManFactory.CreatSuperMan("child"); 47 tSuperMan.SuperManTalent(); 48 return 0; 49 }
2)被调用者:
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : FactoryMethodPattern.c 5 * Description : 工厂方法模式 6 本文件是超人生产工厂的具体实现 7 以进生产超人举例 8 9 * Created : 2017.07.31. 10 * Author : Yu Weifeng 11 * Function List : 12 * Last Modified : 13 * History : 14 ******************************************************************************/ 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include "FactoryMethodPattern.h" 19 20 21 void AdultTalent(); 22 #define newAdultTalent {AdultTalent} 23 void ChildTalent(); 24 #define newChildTalent {ChildTalent} 25 26 /***************************************************************************** 27 -Fuction : CreatSuperMan 28 -Description : 公有函数 29 -Input : 30 -Output : 31 -Return : 32 * Modify Date Version Author Modification 33 * ----------------------------------------------- 34 * 2017/07/31 V1.0.0 Yu Weifeng Created 35 ******************************************************************************/ 36 T_SuperMan CreatSuperMan(char *i_strType) 37 { 38 T_SuperMan tSuperMan={NULL}; 39 if(0==strcmp("adult",i_strType)) 40 { 41 tSuperMan=(T_SuperMan)newAdultTalent; 42 } 43 else if(0==strcmp("child",i_strType)) 44 { 45 tSuperMan=(T_SuperMan)newChildTalent; 46 } 47 else 48 { 49 printf("CreatSuperMan err,UnkownType:%s",i_strType); 50 } 51 return tSuperMan; 52 }
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : FactoryMethodPattern.h 5 * Description : 工厂方法模式 6 7 * Created : 2017.07.31. 8 * Author : Yu Weifeng 9 * Function List : 10 * Last Modified : 11 * History : 12 ******************************************************************************/ 13 #ifndef FACTORY_METHOD_PATTERN_H 14 #define FACTORY_METHOD_PATTERN_H 15 16 typedef struct SuperMan 17 { 18 void (*SuperManTalent)(); 19 20 }T_SuperMan; 21 22 typedef struct SuperManFactory 23 { 24 T_SuperMan (*CreatSuperMan)(char *i_strSuperManType); 25 26 }T_SuperManFactory; 27 28 29 30 T_SuperMan CreatSuperMan(char *i_strType); 31 #define newSuperManFactory {CreatSuperMan} 32 33 34 #endif
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : AdultSuperMan.c 5 * Description : 工厂方法模式 6 本文件是成年超人的具体实现 7 8 * Created : 2017.07.31. 9 * Author : Yu Weifeng 10 * Function List : 11 * Last Modified : 12 * History : 13 ******************************************************************************/ 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include "FactoryMethodPattern.h" 18 19 20 21 /***************************************************************************** 22 -Fuction : AdultTalent 23 -Description : 公有函数 24 -Input : 25 -Output : 26 -Return : 27 * Modify Date Version Author Modification 28 * ----------------------------------------------- 29 * 2017/07/31 V1.0.0 Yu Weifeng Created 30 ******************************************************************************/ 31 void AdultTalent() 32 { 33 printf("超人力大无穷 "); 34 35 }
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : ChildSuperMan.c 5 * Description : 工厂方法模式 6 本文件是未成年超人的具体实现 7 8 * Created : 2017.07.31. 9 * Author : Yu Weifeng 10 * Function List : 11 * Last Modified : 12 * History : 13 ******************************************************************************/ 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include "FactoryMethodPattern.h" 18 19 20 21 /***************************************************************************** 22 -Fuction : ChildTalent 23 -Description : 公有函数 24 -Input : 25 -Output : 26 -Return : 27 * Modify Date Version Author Modification 28 * ----------------------------------------------- 29 * 2017/07/31 V1.0.0 Yu Weifeng Created 30 ******************************************************************************/ 31 void ChildTalent() 32 { 33 printf("小超人的能力是刀枪不入,快速运动 "); 34 35 }
3)执行结果:
book@book-desktop:/work/projects/test/DesignPatterns/FactoryMethodPattern$ gcc -o FactoryMethodPatternUsage AdultSuperMan.c ChildSuperMan.c FactoryMethodPattern.c FactoryMethodPatternUsage.c
book@book-desktop:/work/projects/test/DesignPatterns/FactoryMethodPattern$ ./FactoryMethodPatternUsage
------------生产成年超人:------------
超人力大无穷
-----------生产未成年超人:-----------
小超人的能力是刀枪不入,快速运动
4)详细代码:
https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/CreationalDesignPatterns/FactoryMethodPattern
三、使用场景
1.工厂方法模式是new对象的替代品,所以在所有需要生成对象的地方都可以使用,但是需要慎重地考虑是否增加一个工厂类进行管理,增加代码的复杂度。
2.需要灵活的,可扩展的框架时,可以考虑采用工厂方法模式。
3.可以用在异构项目中,用一个具体的工厂类进行管理,减少与外围系统的耦合。
4.可以使用在测试驱动开发的框架下。例如,测试一个类A,就需要把与类A有关联关系的类B也同时产生出来,可以
使用工厂方法模式把类B虚拟出来,避免类A与类B的耦合。
四、优点
1.良好的封装性,代码结构清晰,实现了统一管理各个实现类
一个对象创建是具有条件约束的,如一个调用者需要一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,降低模块间的耦合。
2.工厂方法模式的扩展性非常优秀
在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以完成拥抱变化。
3.屏蔽产品类
产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化。
4.工厂方法模式是典型的解耦框架。
高层模块只需要知道产品的抽象类,其他的实现类都不用关心。
五、工厂方法模式的扩展
1.缩小为简单工厂模式
一个模块仅需要一个工厂类,没有必要把它产生出来,使用静态的方法就可以了。
2.升级为多个工厂类
在复杂的应用中一般采用多工厂的方法,然后再增加一个协调类,避免调用者与各个子工厂交流,协调类的作用是封装子工厂类,对高层模块提供统一的访问接口
3.替代单例模式
单例模式的核心要求就是在内存中只有一个对象,通过工厂方法模式也可以只在内存中生产一个对象。
4.延迟初始化
一个对象被消费完毕后,并不立科释放,工厂类保持其初始状态,等待再次被使用。
六、与其他模式的区别
1、工厂方法模式与建造者模式
工厂方法模式注重的是整体对象的创建方法,而建造者模式注重的是部件构建的过程。具体来说,
1)意图不同
在工厂方法模式里,我们关注的是一个产品整体;但在建造这模式中,关注的是 由零件一步一步地组装出产品对象。
简单的说,工厂模式是一个对象创建的粗线条应用,建造者模式则是通过细线条勾勒出一个复杂对象,关注的是产品组成部分的创建过程。
2)产品的复杂度不同
工厂方法模式创建的产品一般都是单一性质产品,都是一个模样;而建造者模式创建的则是一个复合产品,它由各个部件复合而成,部件不同产品对象当然不同。这不是说工厂方法模式创建的对象简单,而是指它们的粒度大小不同。一般来说工厂方法模式的对象粒度比较粗,建造者模式的产品对象粒度比较细。
两种模式的选择,完全取决于在做系统设计时的意图,如果需要详细关注一个产品部件的生产、安装步骤,则选择建造者,否则选择工厂方法模式。