文件名称:从模式讲到设计模式再到面向对象设计模式
文件大小:8KB
文件格式:TXT
更新时间:2011-10-17 16:11:37
设计模式之抽象工厂
在讲抽象工厂之前,要从模式开始讲起 先来看看模式的起源: 多年以前,有一位名叫克里斯多佛·亚历山大(英文名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