[设计模式3]--工厂(Factory)模式
原文出处:http://blog.csdn.net/lwbeyond/article/details/7528309
工厂模式属于创建型模式,大致可以分为三类,简单工厂模式、工厂方法模式、抽象工厂模式。
一. 简单工厂模式
简单工厂模式,它的主要特点是需要在工厂类中做判断,从而创造相应的产品。当增加新的产品时,就需要修改工厂类。举个例子,有一家电子产品生产厂家,它只有一个工厂,能够生产两种型号的产品,A 和 B。可以想像一下,A是电吹风,B是电风扇。客户需要什么样的吹风类产品,一定要显示地告诉生产工厂。
代码实现:
- enum CTYPE {PRODUCT_A, PRODUCT_B};
- //抽象产品类
- class Product
- {
- public:
- virtual void Show() = 0;
- };
- //具体产品A
- class ProductA: public Product
- {
- public:
- void Show() { cout<<"Product A"<<endl; }
- };
- //具体产品B
- class ProductB: public Product
- {
- public:
- void Show() { cout<<"Product B"<<endl; }
- };
- //唯一的工厂,可以生产两种型号的产品,在内部判断
- class Factory
- {
- public:
- Product* CreateProduct(enum CTYPE ctype)
- {
- if(ctype == PRODUCT_A) //工厂内部判断
- return new ProductA(); //生产产品A
- else if(ctype == PRODUCT_A)
- return new ProductB(); //生产产品B
- else
- return NULL;
- }
- };
- int main()
- {
- Factory fac; //工厂
- Product *pro = fac.CreateProduct(PRODUCT_A);//生产产品A
- pro->Show();
- return 0;
- }
缺点:
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
打个比方:
这个工厂在刚建厂时,就要事先把以后的要生产的产品考虑好,部门划分好。如果要生产新的产品,就要改变工厂的空间布局,部门也要重新划分,这是很不利的。当然如果工厂以后发展不大,也就是创建的对象比较少时,还是可以用的。
二. 工厂方法模式
所谓工厂方法模式,是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
还以刚才的例子解释,这家电子厂赚了不少钱,于是决定再开设一个厂,其中一个工厂专门用来生产A型号的产品,也就是只生产电吹风,而另一工厂专门用来生产B型号的产品,也就是只生产电风扇,这样分工明确了。以后客户要再下定单时,可以直接找到相关的工厂了,比如要A型号的产品,就找A工厂要,不再担心下的定单是A,生产出来的是B产品了。
代码实现:
- class Product
- {
- public:
- virtual void Show() = 0;
- };
- //产品A
- class ProductA: public Product
- {
- public:
- void Show()
- {
- cout<<"Product A"<<endl;
- }
- };
- //产品B
- class ProductB: public Product
- {
- public:
- void Show()
- {
- cout<<"Product B"<<endl;
- }
- };
- //抽象工厂
- class Factory
- {
- public:
- virtual Product* CreateProduct() = 0;
- };
- //生产A的工厂
- class FactoryA: public Factory
- {
- public:
- Product* CreateProduct()
- {
- return new ProductA;
- }
- };
- //生产B的工厂
- class FactoryB: public Factory
- {
- public:
- Product* CreateProduct()
- {
- return new ProductB;
- }
- };
- int main()
- {
- Factory* fac = new FactoryA(); //A工厂
- Product* p = fac->CreateProduct(); //生产产品
- p->Show();
- return 0;
- }
其实你会发现,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行,你想要加功能,本来是改工厂类的,而现在是修改客户端。
这有什么好处呢?举个例子,有三个客户原来要A产品,现在改卖B产品,在代码中体现为:
简单工厂的处理:
- Factory fac; //工厂
- Product *pro1 = fac.CreateProduct(PRODUCT_A);//生产产品A
- Product *pro2 = fac.CreateProduct(PRODUCT_A);//生产产品A
- Product *pro3 = fac.CreateProduct(PRODUCT_A);//生产产品A
- //改为B产品,这里要改三个地方
- //Product *pro1 = fac.CreateProduct(PRODUCT_B);//生产产品B
- //Product *pro2 = fac.CreateProduct(PRODUCT_B);//生产产品B
- //Product *pro3 = fac.CreateProduct(PRODUCT_B);//生产产品B
- pro1->Show();
- pro2->Show();
- pro3->Show();
工厂方法的处理:
- Factory* fac = new FactoryA(); //A工厂
- //改为B产品,这里只改一个地方
- //Factory* fac = new FactoryB(); //B工厂
- Product* pro1 = factory_A->CreateProduct(); //生产产品
- Product* pro2 = factory_A->CreateProduct(); //生产产品
- Product* pro3 = factory_A->CreateProduct(); //生产产品
- pro1->Show();
- pro2->Show();
- pro3->Show();
这里可以看到工厂方法的好处了吧,工厂方法模式是简单工厂模式的进一步抽象和推广,它集中封装了对象的创建,使得要更换产品时,不需要做大的改动就可以实现,降低了客户程序与产品对象的耦合。
优点:
相对于简单工厂模式来说,这样分工更加明确,当需要新产品时,就建一个新的工厂,而不是对原工厂类进行修改。这样做满足了"开放-封闭"原则,即可以扩展,不可修改。
缺点:
1. 每增加一种产品,就需要增加一个对象的工厂。在C++实现中,就是要定义一个个的工厂类。显然,相比简单工厂模式,工厂方法模式需要更多的类定义。
2. Factory 模式仅仅局限于一类类(就是说 Product 是一类,有一个共同的基类),如果我们要为不同类的类提供一个对象创建的接口,那就要用AbstractFactory了。
打个比方:
如果这家公司发展迅速,推出了很多新的产品,那么就要开设相应的新工厂,一种产品一个工厂。这对于客户来说是好事,分工明确了白;但对于工厂自己来说开销也变大了。
如要我想要生产核心芯片,但是芯片不是产品,不能继承于product类。因为产品和零部件,不是一类。
三. 抽象工厂模式
抽象工厂模式,它定义为提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
还以上面的例子解释,这家公司经营的还不错,针对其核心技术都申请了专利,后来生始生产相关电子芯片了 (像三星一样,即生产产品也生产芯片)。对于这种情况,我们不能在抽象产品类上继承一个零部件,因为产品和芯片没有什么共同之处,完全是两个领域。你要做芯片,就要专心做,当成一个新的领域,不能用以前产品的那一套流程。这样划分才明确,才能更好的实现高内聚,低耦合的明标。
- //抽象产品类
- class Product
- {
- public:
- virtual void Show() = 0;
- };
- //产品A
- class ProductA: public Product
- {
- public:
- void Show()
- {
- cout<<"Product A"<<endl;
- }
- };
- //产品B
- class ProductB: public Product
- {
- public:
- void Show()
- {
- cout<<"Product B"<<endl;
- }
- };
- //抽象芯片类
- class Chip
- {
- public:
- virtual void Show() = 0;
- };
- //芯片A
- class ChipA: public Chip
- {
- public:
- void Show()
- {
- cout<<"Chip A"<<endl;
- }
- };
- //芯片B
- class ChipB: public Chip
- {
- public:
- void Show()
- {
- cout<<"Chip B"<<endl;
- }
- };
- //抽象工厂类
- class Factory
- {
- public:
- virtual Product* CreateProduct() = 0;
- virtual Chip* CreateChip() = 0;
- };
- //生产A的工厂
- class FactoryA: public Factory
- {
- public:
- Product* CreateProduct() //产品
- {
- return new ProductA;
- }
- Chip* CreateChip() //芯片
- {
- return new ChipA;
- }
- };
- //生产B的工厂
- class FactoryB: public Factory
- {
- public:
- Product* CreateProduct() //产品
- {
- return new ProductB;
- }
- Chip* CreateChip() //芯片
- {
- return new ChipB;
- }
- };
- int main()
- {
- Factory* factury = new FactoryA(); //A工厂
- Product* product = factury->CreateProduct(); //生产产品
- Chip* chip = factury->CreateChip(); //生产芯片
- product->Show();
- chip->Show();
- return 0;
- }
我们可以发现,抽象工厂比工厂模式所能处理的产品更多,最关健的是这些产品有不同的基类。
优点:
1. AbstractFactory 模式关键就是将这一组对象的创建封装到一个用于创建对象的工厂类(ConcreteFactory)中,维护这样一个工厂创建类总比维护 n 多相关对象的创建过程要简单的多。
2. 它的最大好处是易于交换产品系列,比如我要B工厂的产品,只需要在客户端代码修改一处即可。
打个比方:
这时客户只要知道A工厂是生产A类的产品和芯片的,B工厂是生产B类的,其它都不用关心,只要想要与A类相关的东东就去找A就行了。
四. 总结:
1. 简单工厂模式,所有的产品都在工厂类中进行生产。功能单一时,没有什么问题,但是当增加很多新产品时,就要不断的修改产品类,易于出错,也违反了对修改是封闭的原则。
2. 工厂方法模式,每个工厂生产一种产品,这样分工更加明确。当增加新产品时,只需增加一个工厂类,而不用修改原有工厂类,这样工厂类的耦合度就降低了。
3. 抽象工厂模式,比工厂方法模式处理的情况更多。主要是对不同产品的处理,这时的工厂能够生产多种产品,这多种产品虽然没有共同基类,但是却属于一类,具体体现在都是由同一个工厂生产。
[设计模式3]--工厂(Factory)模式的更多相关文章
- Head First 设计模式 —— 04. 工厂 (Factory) 模式
思考题 如何将实例化具体类的代码从应用中抽离,或者封装起来,使它们不会干扰应用的其他部分? P111 将实例化具体类的代码放入一个对象中管理,通过不同入参决定实例化具体的类 简单工厂 不是23种GOF ...
- 设计模式--简单工厂(Factory)模式
温故而知新,看了以前写的博文<Asp.net读取Excel文件 2>http://www.cnblogs.com/insus/archive/2011/05/05/2037808.html ...
- 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)
原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...
- Java设计模式之工厂方法模式(转) 实现是抽象工厂?
Java设计模式之工厂方法模式 责任编辑:覃里作者:Java研究组织 2009-02-25 来源:IT168网站 文本Tag: 设计模式 Java [IT168 技术文章] ...
- php设计模式之工厂方法模式
php设计模式之工厂方法模式 工厂方法模式 工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Pol ...
- C#设计模式(3)——工厂方法模式
一.概念:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 二.代码实现 namespace 设计模式之工厂方法模式 { /// <summary&g ...
- C#设计模式(3)——工厂方法模式(转)
C#设计模式(3)——工厂方法模式 一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过 ...
- C#设计模式-2工厂方法模式(Factory Method)
什么是工厂模式?类比生活中的概念,当我们需要打电话的时候,我们需要一部手机,我们通常会选择直接去卖手机的实体店买.但在程序设计中,当我们需要调用一个类(PhoneA或PhoneB)的方法的时候,我们往 ...
- 设计模式-03工厂方法模式(Factory Method Pattern)
插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...
随机推荐
- Zookeeper Hello World
1.Zookeeper的安装使用 在官网上下载zk的安装包(http://labs.renren.com/apache-mirror/zookeeper/),解压后cd到zk的目录下. 单机版安装方法 ...
- centos php php-fpm install
好记性不如烂笔头,把自己安装的步骤记录下来 1.下载php-5.2.8以及php-5.2.8-fpm-0.5.10.diff.gz,放到/usr/local/src目录 2.解压php-5.2.8到/ ...
- Apache Spark是什么?
简单地说, Spark是发源于美国加州大学伯克利分校AMPLab的大数据分析平台,它立足于内存计算,从多迭代批量处理出发,兼顾数据仓库. 流处理和图计算等多种计算范式,是大数据系统领域的全栈计算平台. ...
- centos 安装redis php
$ wget http://download.redis.io/releases/redis-3.0.7.tar.gz $ tar xzf redis-3.0.7.tar.gz $ cd redis- ...
- SOA和Web Service介绍
博客园中关于SOA和Web Service的介绍 http://www.cnblogs.com/talentbuilder/archive/2010/05/04/1727044.html http:/ ...
- Lotus 迁移到Exchange 2010 之准备使用Transport 同步Lotus 相关信息!
这里我们先来分析下Lotus迁移到Exchange2010 的一些原理,由于存在一定周期的共存时间,因此在共存期间必须来实现相应的同步计划,整个同步计划包含了如下的同步计划:
- Spring REST实践之Error Handling
Error Responses 在REST API中,HTTP状态码有非常重要的作用.API开发者应该坚持为每一个请求返回一个正确合适的状态码,而且应该在响应body中包含有用的.细粒度的错误信息.这 ...
- UI:UITableView表视图
表视图 UITableView,iOS中最重要的视图,随处可⻅见. 表视图通常⽤用来管理⼀一组具有相同数据结构的数据. UITableView继承⾃自UIScrollView,所以可以滚动,表视图的每 ...
- 【转】HTTP HEAD
原文出自:http://kb.cnblogs.com/page/92320/ HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议.HTTP协议采用 ...
- javascript第三方组件
一.一个javascript文件上传组件.转载:http://www.cnblogs.com/fumj/archive/2012/12/07/2806673.html http://fineuploa ...