C++设计模式——工厂方法模式
» 本文链接:http://www.jellythink.com/archives/62
» 订阅本站:http://www.jellythink.com/feed
问题描述
之前讲到了C++设计模式——简单工厂模式,由于简单工厂模式的局限性,比如:工厂现在能生产ProductA、ProductB和ProductC三种产品了,此时,需要增加生产ProductD产品;那么,首先是不是需要在产品枚举类型中添加新的产品类型标识,然后,修改Factory类中的switch结构代码。是的,这种对代码的修改,对原有代码的改动量较大,易产生编码上的错误(虽然很简单,如果工程大了,出错也是在所难免的!!!)。这种对代码的修改是最原始,最野蛮的修改,本质上不能称之为对代码的扩展。同时,由于对已经存在的函数进行了修改,那么以前进行过的测试,都将是无效的,所有的测试,都将需要重新进行,所有的代码都需要进行重新覆盖。这种,增加成本,不能提高效率的事情,在公司是绝对不允许的(除非昏庸的PM)。出于种种原因,简单工厂模式,在实际项目中使用的较少。那么该怎么办?怎么办呢?需要对原有代码影响降到最小,同时能对原有功能进行扩展。
UML类图
那么今天介绍的工厂方法模式,就隆重登场了。它只是对简单工厂模式的扩展,在GOF的介绍中,它们是合并在一起的,而我则是单独分开进行讲解的,就是为了区分二者的利弊,便于大家在实际项目中进行更好的把握与应用。工厂方法模式是在简单工厂模式的基础上,对“工厂”添加了一个抽象层。将工厂共同的动作抽象出来,作为抽象类,而具体的行为由子类本身去实现,让子类去决定生产什么样的产品。
如图,FactoryA专心负责生产ProductA,FactoryB专心负责生产ProductB,FactoryA和FactoryB之间没有关系;如果到了后期,如果需要生产ProductC时,我们则可以创建一个FactoryC工厂类,该类专心负责生产ProductC类产品。由于FactoryA、FactoryB和FactoryC之间没有关系,当加入FactoryC加入时,对FactoryA和FactoryB的工作没有产生任何影响,那么对代码进行测试时,只需要单独对FactoryC和ProductC进行单元测试,而FactoryA和FactoryB则不用进行测试,则可省去大量无趣无味的测试工作。
适用场合
工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
- 在设计的初期,就考虑到产品在后期会进行扩展的情况下,可以使用工厂方法模式;
- 产品结构较复杂的情况下,可以使用工厂方法模式;
由于使用设计模式是在详细设计时,就需要进行定夺的,所以,需要权衡多方面的因素,而不能为了使用设计模式而使用设计模式。
代码实现
/* ** FileName : FactoryMethodPatternDemo ** Author : Jelly Young ** Date : 2013/11/18 ** Description : More information, please go to http://www.jellythink.com */ #include <iostream> using namespace std; class Product { public: ; }; class ProductA : public Product { public: void Show() { cout<< "I'm ProductA"<<endl; } }; class ProductB : public Product { public: void Show() { cout<< "I'm ProductB"<<endl; } }; class Factory { public: ; }; class FactoryA : public Factory { public: Product *CreateProduct() { return new ProductA (); } }; class FactoryB : public Factory { public: Product *CreateProduct() { return new ProductB (); } }; int main(int argc , char *argv []) { Factory *factoryA = new FactoryA (); Product *productA = factoryA->CreateProduct(); productA->Show(); Factory *factoryB = new FactoryB (); Product *productB = factoryB->CreateProduct(); productB->Show(); if (factoryA != NULL) { delete factoryA; factoryA = NULL; } if (productA != NULL) { delete productA; productA = NULL; } if (factoryB != NULL) { delete factoryB; factoryB = NULL; } if (productB != NULL) { delete productB; productB = NULL; } ; }
2013年11月18日 于大连、东软。
C++设计模式——工厂方法模式的更多相关文章
- 4. 星际争霸之php设计模式--工厂方法模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- JAVA设计模式--工厂方法模式
工厂方法设计模式 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关.是具体工厂角色必须实现的接口或者必须继承的父类.在java中它由抽象类或者接口来实现.具体工厂角色:它含有和具体业务逻辑有关 ...
- 深入浅出设计模式——工厂方法模式(Factory Method)
介绍在简单工厂模式中,我们提到,工厂方法模式是简单工厂模式的一个延伸,它属于Gof23中设计模式的创建型设计模式.它解决的仍然是软件设计中与创建对象有关的问题.它可以更好的处理客户的需求变化. 引入我 ...
- 设计模式--工厂方法模式(Factory method pattern)及应用
面向对象的好处: 通过封装,继承,多态把程序的耦合度降低. 用设计模式可以使程序更加灵活,容易修改,且易于复用. 1. 工厂方法模式 Define an interface for creating ...
- 我的Java设计模式-工厂方法模式
女朋友dodo闹脾气,气势汹汹的说"我要吃雪糕".笔者心里啊乐滋滋的,一支雪糕就能哄回来,不亦乐乎?! 但是,雪糕买回来了,她竟然说"不想吃雪糕了,突然想吃披萨" ...
- 设计模式 — 工厂方法模式(Factory Method)
在开发系统中,经常会碰到一个问题.现在需要实现的一些功能,但是这个功能模块以后一定是需要扩展的,那么现在开发中就不仅要实现现在的功能,还要考虑以后的扩展.那么为了系统的健壮,扩展就要遵循开闭原则(简单 ...
- C#设计模式--工厂方法模式
0.C#设计模式-简单工厂模式 设计模式: 工厂方法模式(Factory Method Pattern) 介绍:简单工厂模式是要在工厂类中通过数据来做个决策,在工厂类中的多个类中实例化出来其中一个要用 ...
- Java设计模式—工厂方法模式&抽象工厂模式
工厂方法模式与抽象工厂模式都是设计模式中重要而且常见的模式. 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 通用类图如下: 在 ...
- 设计模式——工厂方法模式(Factory Method)
原文地址:http://www.cnblogs.com/Bobby0322/p/4179921.html 介绍 在简单工厂模式中,我们提到,工厂方法模式是简单工厂模式的一个延伸,它属于Gof23中设计 ...
随机推荐
- Linux设备模型 学习总结
看LDD3中设备模型一章,觉得思维有些混乱.这里从整体的角度来理理思路.本文从四个方面来总结一些内容: 1.底层数据结构:kobject,kset.2.linux设备模型层次关系:bus_type,d ...
- ASP.NET(C#)--Repeater中生成“序号”列
需求介绍:在Repeater(Table)中加入“序号”列,从1开始自增,步长为1. 思路:因为“序号”跟Repeater的行号有关,所以要在Repeater的ItemDataBound事件中输出“序 ...
- LinqToDataTable
/// <summary> /// 下面通过一个方法来实现返回DataTable类型 /// LINQ返回DataTable类型 /// </summary> /// < ...
- 判断jquery是否已经加载,如果没有动态加载
方法一: // Only do anything if jQuery isn't defined if (typeof jQuery == 'undefined') { if (typeof $ == ...
- javaSE27天学习目录
第一阶段(java基础知识) 计算机基础知识 Java开发环境的搭建和应用 机制转换 有符号数据表示法(原码.反码.补码) Java语句基础(关键字.标识符.注释.常量.变量.数据类型.运算符) ...
- POJ 1195
Mobile phones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 13774 Accepted: 6393 De ...
- Linux shell实现Mysql异地备份数据库
#--------------------------Mysqldump异地备份-----------------# #!/bin/bash #start mysqldump back /usr/bi ...
- c#操作Zip压缩文件
SharpZipLib 文件/文件夹压缩 一.ZipFile ZipFile类用于选择文件或文件夹进行压缩生成压缩包. 常用属性: 属性 说明 Count 文件数目(注意是在ComitUpdat之后才 ...
- YARN内存使用优化配置
在Hadoop2.0中, YARN负责管理MapReduce中的资源(内存, CPU等)并且将其打包成Container. 这样可以精简MapReduce, 使之专注于其擅长的数据处理任务, 将无需考 ...
- Discuz X3.2 分区 gid 完美伪静态方法 Apache/Nginx
Discuz 官方给出的伪静态规则并不完整,只实现了部分的伪静态设置及规则,分区 gid 仍然是 forum.php?gid=xxx 的形式,对于有强迫症的我是无法忍受的,下面给出分区 gid 的伪静 ...