“工厂模式和抽象工厂的区别”的认识

 

这几天再次复习了工厂模式和抽象工厂模式,发现工厂模式和抽象工厂简直太像了。

工厂模式:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

仔细分析一下发现如下区别和联系:

1、工厂模式的一个工厂只能生产一种产品;抽象工厂生产多个产品(产品族);

2、在工厂模式的工厂中增加生产产品的能力其实就变成了抽象工厂;

3、抽象工厂中的接口要使用抽象的类,这样即使拓展产品也不会导致原有具体工厂直接报错“未实现接口”;这样也使得具体工厂可以只生产部分产品,这样就保证了开闭原则。

总结:其实工厂模式和抽象工厂模式的就是工厂生产产品的能力差别,从工厂模式改进到抽象工厂在进行总结的时候把设计思想描述的太高了。

我认为仅此而已。欢迎指正。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在讲抽象工厂之前,要从模式开始讲起 先来看看模式的起源:  多年以前,有一位名叫克里斯多佛·亚历山大(英文名Christopher Alexander)的建筑师为了研究优秀的设计有没有共性这一问题,他对建筑物、城镇、街道等,以及人类为自己所建造的各种生活空间进行了大量的观察。他发现,在特定的建筑物中,优秀的结构都有一些共同之处,虽然它们结构互不相同,但可能都具有很高的质量。  例如:两个门廊虽然结构上不同,但都具有很高的质量。不同的建筑可能是为了解决不同的问题。一个门廊可能是走道和前门之间的过渡,而另一个门廊可能是为了在天气炎热时提供阴凉。或许,两个门廊在解决同一个问题(过渡)时,也可采用不同的方式。亚历山大看到了这一点,他知道结构不能与要解决的问题分离,因此,在寻找和描述设计质量一致性的探求中,亚历山大认识到,必须观察为了解决同样问题而设计的不同结构。    亚历山大发现,通过这样的方式——观察解决相似问题的不同结构,可以缩小关注范围,从而看清优秀设计之前的相似之处。他将这种相似之处称之为模式。   他对模式的定义是“在某一环境下某个问题的一种解决方案”。每个模式都描述了一个在我们的环境中会不断重复出现的问题,并叙述了这个问题解决方案的要素,通过这种方式,同一解决方案能够被反复应用无数次,而每一次使用的具体方式可以不同。 亚历山大对模式的描述包括如下四项: 1、模式的名称 2、模式的目的,也就是解决的问题 3、实现方法 4、为了实现该模式我们必须考虑的限制和约束因素   在20世纪90年代,软件界有好多人在想,软件开发中是否存在以某种相同的方式解决不断重复出现的问题,是否可以用模式的方法来设计软件,经过他们不断的总结,答案是肯定的。   以现实生活中“路”的生成为例:“地上本没有路,走的人多了便成了路”。同理,设计模式是经验的总结与传承。不论是建筑设计模式,还是软件设计模式,这些经验都源于“人”,所以说人是一个经验性动物。在我们每天的生活或工作环境中,如果存在一些会影响我们生活或者工作的现象或问题,我们就对这些现象或问题做出一个判断或处理。这些经验总结源于实践,也服务于实践。从“模式”到“设计模式”,再到“面向对象设计模式”,这是一个从广泛到具体的过程。“设计模式”是一个广泛的概念,它既可以指建筑中的设计模式,也可以指软件开发中的设计模式等。“面向对象设计模式”是可复用面向对象软件的基础。三者的基本描述如下: 1、每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案。 2、设计模式描述了软件开发过程中某一类常见问题的一般性解决方案。 3、面向对象设计模式是对在特定场景下,解决一般设计问题中类与相互通信对象的描述。 目前最有影响力的书籍是:《设计模式:可复用面向对象软件的基础》,它共编录了23种设计模式,分三大类别:创建型模式、结构型模式、行为模式,其中有一种创建型模式是抽象工厂设计模式。 在学习抽象工厂设计模式之前,要先知道简单工厂模式   众所周知,从结构可以看出,简单工厂模式中的工厂依赖于所有的子类产品,客户只需知道父类产品和工厂即可。工厂是整个模式的核心,以不变应万变。它虽然使对象的创建与使用进行了分离,但一次只能创建一个对象。它不能实现一次创建一系列相互依赖对象的需求,为此我们需要学习抽象工厂设计模式。   打个比方:我想买一个移动硬盘,那么我只要告诉你硬盘工厂生产一块120G的移动硬盘就可以了!至于你工厂内如何生产,那不是我关心的问题(哪怕是你工厂能生产40G、80G、160G的,也与我没有关系),我只要给你工厂一个条件(120G),工厂给我一块120G的硬盘就可以了,其它的我不想知道,也不需要知道不是吗?那么,不难看出,做为客户,我们只要知道工厂和父类产品就可以了,还工厂则是提供了一个接口,告诉客户工厂可以生产移动硬盘!可以看出这个工厂只能生产移动硬盘这种产品!   现在问题来了,移动硬盘坏了,我还要再一块硬盘,同时我还想再买一个CPU,再买一个显示器,那这时怎么办,我们要去每个工厂都告诉一下吗?答案那是不可能的(因为我也哪个工厂生产CPU,哪个工厂生产显示器)。那我们为什么不去一个既有CPU卖,又有显示器卖,还有移动硬盘卖的地方呢? 那么这时候我们只有有需求就可以被满足了。这里我们就把这 种地方抽象为电脑抽象工厂。电脑这个抽象工厂都是由什么组成的呢(比如:显示器、CPU、显卡、主板、内存、硬盘等),那么这里的产品因为没有被真正的制作出来,这里只是知道电脑由什么组成,所以我们把这样的产品称之为抽象产品。 结论:抽象工厂生产抽象产品!   现在,如果一个公司(联想)成立了,这家公司想打造一个自己的电脑品牌,那么这家公司就应该有可以生产所有电脑组成所需的产品对吧?(比如:显示器、CPU、显卡、主板、内存、硬盘等等,即使不是自己工厂生产的,那么也要从新把这个产品打上自己的商标),好了,下面开始要生产自己的显示器了。问题来了,电脑中的显示器(也就是抽象工厂中的抽象产品)有没有公有接口或者说是方法呢?一定是有的,比如显示器都可以显示吧,都有一个数据线与电脑提供的接口相连接吧等等。这也就要求联想在生产自己的显示器的时候要遵循显示器(抽象产品)的规则。然后在这个基础上,再增加自己显示器的功能,以便对抗其它生产商。如果再有一家公司(戴尔)也与联想的一致. 结论:实体工厂生产实体产品 结论:抽象产品提供实体产品的访问接口 结论:实体产品实现自己的功能。 如果现在大家还不太明白,那也不要紧,我现在用伪代码写一下: 抽象工厂 public abstract class 电脑抽象工厂 {   //大家都学过用接口做为返回值类型吧,众所周知,接口可以做参数传递同时也可做为返回值,这里不再讲解接口.   public abstract 显示器抽象产品接口 生产显示器的方法();   public abstract CPU抽象产品接口 生产CPU抽象产品(); } 抽象产品 public interface 显示器抽象产品接口 {   返回值类型 显示器里的方法1();   返回值类型 显示器里的方法2(); } public interface CPU抽象产品接口 {   返回值类型 CPU里的方法1();   返回值类型 CPU里的方法2(); } 实体工厂 public class 联想电脑工厂 : 电脑抽象工厂//是由电脑抽象工厂派生的 { public override 显示器抽象产品接口 生产显示器的方法()//生产联想显示器实体产品 { return new 联想显示器实体产品(); } public override CPU抽象产品接口 生产CPU抽象产品()//生产联想CPU实体产品 { return new 联想CPU实体产品(); } } public class 戴尔电脑工厂 : 电脑抽象工厂//是由电脑抽象工厂派生的 { public override 显示器抽象产品接口 生产显示器的方法()//生产戴尔显示器实体产品 { return new 戴尔显示器实体产品(); } public override CPU抽象产品接口 生产CPU抽象产品()//生产戴尔CPU实体产品 { return new 戴尔CPU实体产品(); } } 实体产品 联想 public class 联想显示器实体产品:显示器抽象产品接口 {   public 返回值类型 显示器里的方法1()   {   //实现   }   public 返回值类型 显示器里的方法2()   {    //实现   } } public class 联想CPU实体产品:CPU抽象产品接口 { public 返回值类型 CPU里的方法1() { //实现 } public 返回值类型 CPU里的方法2() { //实现 } } 戴尔 public class 戴尔显示器实体产品:显示器抽象产品接口 { public 返回值类型 显示器里的方法1() { //实现 } public 返回值类型 显示器里的方法2() { //实现 } } public class 戴尔CPU实体产品:CPU抽象产品接口 { public 返回值类型 CPU里的方法1() { //实现 } public 返回值类型 CPU里的方法2() { //实现 } } 如果大家对抽象工厂、抽象产品、实体工厂、实体产品已经能够理解,那么请向下看: 为了在调用时方便,我们在抽象工厂里加一个创建实体工厂的方法 public abstract class 电脑抽象工厂 { //创建实体工厂 public static 电脑抽象工厂 选择实体工厂(string typename) { 电脑抽象工厂 抽象工厂实体 = null; switch (typename) { case "联想": 抽象工厂实体 = new 联想电脑工厂(); break; case "戴尔": 抽象工厂实体 = new 戴尔电脑工厂(); break; } return 抽象工厂实体; } //大家都学过用接口做为返回值类型吧,众所周知,接口可以做参数传递同时也可做为返回值,这里不再讲解接口. public abstract 显示器抽象产品接口 生产显示器的方法(); public abstract CPU抽象产品接口 生产CPU抽象产品(); } 这里在调用的时候就可以这样使用了 public static void Main() { //电脑抽象工厂 电脑实体=电脑抽象工厂.选择实体工厂("戴尔"); 电脑抽象工厂 电脑实体=电脑抽象工厂.选择实体工厂("联想"); 电脑实体.生产显示器的方法(); 电脑实体.生产CPU抽象产品(); //这样,只要传入一个品牌,就可以得到这个品牌的电脑了 } 文章出处:http://www.diybl.com/course/4_webprogram/asp.net/asp_netxl/200898/140200.html

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值