面向对象设计模式纵横谈:Abstract Factory 抽象工厂模式(笔记记录)

     今天是设计模式的第二讲,抽象工厂的设计模式,咱们仍是延续老办法,一步一步的、演变的来说,先来看看一个对象建立的问题。编程

一、如何建立一个对象设计模式

常规的对象建立方法:框架

image 

这样的建立对象没有任何问题,也能够很好的使用。可是若是有需求的变化,好比,若是咱们换了一种道路呢,这时候就出现了问题。ui

new的问题:spa

-实现依赖,不能应对“具体实例化类型”的变化,Road是具体类型,全部使用到Road的地方都须要变化。若是常常变化,怎么解决具体类型的变化呢?
设计

解决思路:3d

-封装变化点——哪里变化,封装哪里对象

-潜台词:若是没有变化,固然不须要额外的封装!blog

 

二、简单工厂模式的由来
继承

先说明一点,“简单工厂模式”没有写在Gof的23种设计模式里面,它是“工厂模式”的引子。

变化点在“对象建立”,所以就封装“对象建立”

面向接口编程——依赖接口(此接口不是语言层面的Interface,此接口能够是:Interface&抽象类),而非依赖实现

最简单的解决方法:

image

这样作,能够隔离客户程序和具体Road类型的变化,客户程序依赖比较稳定的RoadFactory类型,这样一来,客户端的使用的接口就比较稳定了。

 

三、建立一系列相互依赖的对象

一个对象的问题解决了,那多个对象的建立问题怎么解决呢?

假设一个游戏开发场景:

咱们须要构造“道路”、“房屋”、“地道”、“丛林”……等等对象

image

image

 很不错,解决了一批对象的建立问题,这样能够保持客户程序使用接口的稳定性。

四、多批对象的建立

简单工厂的问题:

-不能应对“不一样系列对象”的变化。好比有不一样风格的游戏场景——对应不一样风格的道路、房屋、地道……客户程序相对稳定,可是静态的简单工厂却可能成为变化点。

如何解决:

-使用面向对象的技术来“封装”变化点,咱们就可使用“抽象工厂”设计模式

 

动机(Motivation)

在软件系统中,常常面临着“一系列相互依赖的对象”的建立工做;同时,因为需求的变化,每每存在更多系列对象的建立工做。

如何应对这种变化?如何绕过常规的对象建立方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象建立工做”的紧耦合?

 

意图(Intent)

提供一个接口,让该接口负责建立一系列“相关或者相互依赖的对象”,无需指定它们具体的类。

 

结构(Structure)

image

ProductA1和ProductB1是一个系列,ProductA2和ProductB2是另外一个系列。ConcreteFactory1是建立系列1的工厂方法,ConcreteFactory2是建立系列2的工厂方法。客户程序Client只依赖了AbstractFactory和AbstractProductA、AbstractProductB,也就是客户程序不依赖于具体实现,而是只依赖与抽象类。

若是如今须要建立一个系列3运用到客户程序,咱们只须要再写一个系列3的工厂,继承自AbstractFactory,这个工厂提供了2个实现:

CreateProductA();

CreateProductB();

它们分别返回ProductA3(继承自AbstractProductA)、ProductB3(继承自AbstractProductB)。

也就是说,若是新增了系列3,Client程序能够彻底不用改动,可能只须要该一些配置文件,增长一些新dll就能够应对变化。

 

游戏框架中的AbstractFactory应用

image

image

这个例子里,Road就是AbstractProductA1,Building就是AbstractProductB1,FacilitiesFactory就是AbstractFactory。

 

客户程序

image

能够看出,客户程序依赖的所有是抽象类,在客户程序代码中没有出现过任何具体的实现类。由于在系列须要变化的时候,是不须要改变抽象类的,只是增长一个抽象类的实现而已,又因为客户程序只依赖于抽象,因此系列变化的时候客户程序彻底无需变化。

一个现代风格系列的实现

image

具体现代风格系列工厂实现

image

应用到具体程序(现代风格)

image

应用到具体程序(经典风格)

image

能够看出,风格由Modern改变为Classic的时候,咱们封装好的GameManager客户程序没有改变,这就是咱们想要的结果。GameManager的逻辑很是复杂,如今它的稳定,可以大大方便咱们的工做。

 

AbstractFactory模式的几个要点

1.若是没有应对“多系列对象建立”的需求变化,则没有必要使用AbstractFactory模式,这时候使用简单的静态工厂彻底能够。

2."系列对象"指的是这些对象之间有相互依赖、或做用的关系,例如游戏开发场景中“道路”与“房屋”的依赖,“道路”与“地道”的依赖。

3.AbstractFactory模式主要在于应对“新系列”的需求变更。其缺点在于难以应对“新对象”的需求变更。

4.AbstractFactory模式常常喝FactoryMethod模式共同组合来应对“对象建立”的需求变化。

例如,若是是风格不常常变化,而是其余内容变化(例现在天要添加道路的类、明天要添加沙漠的类),这样用这种抽象工厂模式反而会把系统搞的很糟糕,由于抽象工厂类中的子类变化了,全部实现抽象工厂的类都须要去变化,从新实现,从新编译和部署。

也就是说关键要看变化的方向和轴线在哪里。若是变化的轴线在多风格,那抽象工厂模式就很适用;若是变化的轴线在抽象工厂里面的对象,就最好不要使用这种模式。

 

.NET框架中的AbstractFactory应用

在ASP.Net编译的时候,首先把aspx页面文件先编译成一个类,而后再把CodeBehind又编译成一个类,CodeBehind的类继承自Page类,而aspx页面的类又继承自CodeBehind类。在aspx页面中处理的WebControl和HtmlControl实际上用到了AbstractFactory的运用,可是这个运用更可能是体如今业务层次。

 

Builder模式和AbstractFactory模式的区别

Builder模式更强调的是对象组成部分的构建的过程,并且这个构建的过程很稳定,可是各个组成部分在变化,最后组合成一个总体的对象。

AbstractFactory模式构建的是一系列相互依赖、相互关联的对象集合。

相关文章
相关标签/搜索