您的位置:首页 > 其它

我的设计模式之旅(3)――抽象工厂模式AbstractFactory

2006-08-02 17:33 567 查看
抽象工厂模式,花了一些时间来学习它,它的意图就是“提供一个接口,让该接口负责创建一系列相关或者相互依赖的对象,无需指定它们具体的类”,对于已有系列对象的创建时,根据需要替换起来很方便。但是对于新增系列对象的替换则还是需要像原来一样,最起码要新增加这个我们需要的新类,但是这种良好的结构为我们提供了很方便的扩展方法。个人感觉它的缺点就是不能创建有着不同个数对象的系列,不过应该是可以通过工厂方法来解决的,这个留做以后解决的问题。
看到很多相关文章最后都是付诸于代码的实现,自己感觉TerryLee的就比较好,设计模式设计模式,当然是设计的模式,不是代码的模式。应该是让我们有好的设计,最后代码只是设计的具体表现,让我们的代码看起来更具模块化,相互之间的耦合度更低。
实现设计和实现编码是两个过程,网上写了这么多例子,应该能看出来用来实现一个模式的编码不是一个固定的编码结构,其中可能会有这样那样的变化,但是根据具体项目的需求实现了目的,我认为就是实现了我们的设计。

引一个吕震宇老师文章里很能说明问题的图:



我们就是要实现提供一个AbstractFactory接口来实现系列对象的创建,至于对象怎样创建,他们之间体关系是怎样实现的都不需要客户程序来关心,客户程序需要做的就是使用这个接口就得到了它需要的一系列对象。
上周末在和大家讨论的时候,被问道“最后即使是改一处还是需要修改代码啊?而且对于系列产品的创建为什么不写成一个接口?”,第二个问题比较好解答,因为像我前面说的实现不是一个固定的代码结构。第一个问题在我看了TerryLee的文章后得到了解决,两种方案,一种是将这种修改放到配置文件中,实现运行时的维护,另一种就是利用一个反射的机制来实现,在以后进行扩展时扩展者,甚至都不需要知道源代码,只需要提供给扩展者相应的接口即可实现扩展(厚厚~~~这里很佩服TerryLee的这些思考!很受用!)。
这里我也不想自己再写什么实际应用的例子,尽是对自己学习的一个总结吧,将李建忠老师的例子结合TerryLee的方案,将其再修改完善一下而已,仅是自己的一个练习吧。
首先是我们构建的工厂方法的代码,将其贴在下面。
[align=left] //道路[/align]
[align=left] public abstract class Road[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //房屋[/align]
[align=left] public abstract class Building[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //地道[/align]
[align=left] public abstract class Tunnel[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //丛林[/align]
[align=left] public abstract class Jungle[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public abstract class FacilitiesFactory[/align]
[align=left] {[/align]
[align=left] public abstract Road CreateRoad();[/align]
[align=left] public abstract Building CreateBuilding();[/align]
[align=left] public abstract Tunnel CreateTunnel();[/align]
[align=left] public abstract Jungle CreateJungle();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] //现代风格道路[/align]
[align=left] public class ModernRoad : Road[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //现代风格房屋[/align]
[align=left] public class ModernBuilding : Building[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //现代风格地道[/align]
[align=left] public class ModernTunnel : Tunnel[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //现代风格丛林[/align]
[align=left] public class ModernJungle : Jungle[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] //现代风格[/align]
[align=left] public class ModernFacilitiesFactory : FacilitiesFactory[/align]
[align=left] {[/align]
[align=left] public override Road CreateRoad()[/align]
[align=left] {[/align]
[align=left] return new ModernRoad();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public override Building CreateBuilding()[/align]
[align=left] {[/align]
[align=left] return new ModernBuilding();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public override Tunnel CreateTunnel()[/align]
[align=left] {[/align]
[align=left] return new ModernTunnel();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public override Jungle CreateJungle()[/align]
[align=left] {[/align]
[align=left] return new ModernJungle();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] //古典风格道路[/align]
[align=left] public class ClassicRoad : Road[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //古典风格房屋[/align]
[align=left] public class ClassicBuilding : Building[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //古典风格地道[/align]
[align=left] public class ClassicTunnel : Tunnel[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] //古典风格丛林[/align]
[align=left] public class ClassicJungle : Jungle[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] //古典风格[/align]
[align=left] public class ClassicFacilitiesFactory : FacilitiesFactory[/align]
[align=left] {[/align]
[align=left] public override Road CreateRoad()[/align]
[align=left] {[/align]
[align=left] return new ClassicRoad();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public override Building CreateBuilding()[/align]
[align=left] {[/align]
[align=left] return new ClassicBuilding();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public override Tunnel CreateTunnel()[/align]
[align=left] {[/align]
[align=left] return new ClassicTunnel();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public override Jungle CreateJungle()[/align]
[align=left] {[/align]
[align=left] return new ClassicJungle();[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] class GameManager[/align]
[align=left] {[/align]
[align=left] FacilitiesFactory facilitiesFactory;[/align]
[align=left] [/align]
[align=left] Road road;[/align]
[align=left] Building building;[/align]
[align=left] Tunnel tunnel;[/align]
[align=left] Jungle jungle;[/align]
[align=left] [/align]
[align=left] public GameManager(FacilitiesFactory facilitiesFactory)[/align]
[align=left] {[/align]
[align=left] this.facilitiesFactory = facilitiesFactory;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public void BuildGameFacilities()[/align]
[align=left] {[/align]
[align=left] road = facilitiesFactory.CreateRoad();[/align]
[align=left] [/align]
[align=left] building = facilitiesFactory.CreateBuilding();[/align]
[align=left] [/align]
[align=left] tunnel = facilitiesFactory.CreateTunnel();[/align]
[align=left] [/align]
[align=left] jungle = facilitiesFactory.CreateJungle();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public void Run()[/align]
[align=left] {[/align]
[align=left]// road.AAA();[/align]
[align=left]// building.BBB(road);[/align]
[align=left]// tunnel.CCC();[/align]
[align=left]// jungle.DDD(tunnel);[/align]
[align=left] Console.WriteLine(road);[/align]
[align=left] Console.WriteLine(building);[/align]
[align=left] Console.WriteLine(tunnel);[/align]
[align=left] Console.WriteLine(jungle);[/align]
[align=left] }[/align]
[align=left] }[/align]
这是李建忠老师的例子,具体的应用客户程序如下。
[align=left] public static void Main()[/align]
[align=left] {[/align]
[align=left] GameManager g = new GameManager(new ModernFacilitiesFactory());[/align]
[align=left] g.BuildGameFacilities();[/align]
[align=left] g.Run();[/align]
[align=left] }[/align]
这里提一下其中GameManager g = new GameManager(new ModernFacilitiesFactory());这句话其实是两句合在一起写的,分开如下:
[align=left] FacilitiesFactory f = new ModernFacilitiesFactory();[/align]
[align=left] GameManager g = new GameManager(f);[/align]
TerryLee的第一种改造就是在系列对象不发生系列添加的情况下,使用配置文件来进行例子中场景风格的替换。添加一个App.config文件,在其中加入风格设置的字段。
[align=left]<?xml version="1.0" encoding="utf-8" ?>[/align]
[align=left]<configuration>[/align]
[align=left] <appSettings>[/align]
[align=left] <add key="factoryName" value="ModernFacilitiesFactory"></add>[/align]
[align=left] </appSettings>[/align]
[align=left]</configuration>[/align]
然后,在代码中读取这个配置字段,根据配置字段的值来做实现。首先实现一个构建方法,然后再在客户程序中调用。
[align=left] public static FacilitiesFactory GetInstance()[/align]
[align=left] {[/align]
[align=left] string factoryName = ConfigurationSettings.AppSettings["factoryName"];[/align]
[align=left] FacilitiesFactory f;[/align]
[align=left] switch(factoryName)[/align]
[align=left] {[/align]
[align=left] case "ModernFacilitiesFactory":[/align]
[align=left] f = new ModernFacilitiesFactory();[/align]
[align=left] break;[/align]
[align=left] case "ClassicFacilitiesFactory":[/align]
[align=left] f = new ClassicFacilitiesFactory();[/align]
[align=left] break;[/align]
[align=left] default:[/align]
[align=left] f = null;[/align]
[align=left] break;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] return f;[/align]
[align=left] }[/align]
[align=left] //客户程序[/align]
[align=left] public static void Main()[/align]
[align=left] {[/align]
[align=left] GameManager g = new GameManager(GetInstance());[/align]
[align=left] //GameManager g = new GameManager(new ModernFacilitiesFactory());[/align]
[align=left] g.BuildGameFacilities();[/align]
[align=left] g.Run();[/align]
[align=left] }[/align]
其实还有一种需求就是扩展新的系列对象,如果还是不需要对客户程序进行维护,而仅是添加了新的系列对象的类,那将是很舒服的一件事。这样我们就可以通过添加DLL并配合配置文件的使用,就能在不修改源程序代码的情况下,扩展出我们需要的新的系列对象(这里很佩服TerryLee的这种实现)。
[align=left] public staticFacilitiesFactory GetInstance()[/align]
[align=left] {[/align]
[align=left] string factoryName = ConfigurationSettings.AppSettings["factoryName"];[/align]
[align=left] FacilitiesFactory f;[/align]
[align=left] if(factoryName != "")[/align]
[align=left] f = (FacilitiesFactory)Assembly.Load(factoryName).CreateInstance(factoryName);[/align]
[align=left] else[/align]
[align=left] f = null;[/align]
[align=left] return f;[/align]
[align=left] }[/align]
这样,我们在扩展时仅需将扩展的DLL放在相应的路径下并配合配置文件即实现了我们的扩展。
本文出自 “努力学习的小熊” 博客,转载请与作者联系!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: