设计模式

来源:互联网 发布:手机上js刻度尺滑动 编辑:程序博客网 时间:2024/05/01 04:00
 

旧话重提之-各种工厂模式

一、             序言

 

在所有已知的各种模式中,最重要的和应用范围最广泛的模式应该就是隶属于创建型模式工厂模式了。尤其是在Framework的编程中使用更为广泛,毫不夸张的讲几乎任何一个优秀框架中都有工厂模式的影子。 工厂模式虽然结构比较简单,却集中体现了面向对象设计中最重要的几个特性, 面向抽象、封装、委托、继承、多态在工厂模式中都有很好的体现。 其实说起工厂模式相信大家都不会觉得陌生,甚至更多的朋友都在实际工作过程中不自觉地或者有意识的在使用着它。写这篇文章目的是让不清楚或不熟悉工厂模式的人来系统的了解这种模式设计的思想和如何在实际的软件设计和开发过程中应用。

二、             定义

 

为了把对象的创建过程和使用过程进行分离,定义通用的接口用于创建对象。

 

             

 

三、             叙述几种工厂模式

 

            Template Method

 

从简单到复杂是介绍复杂事物的最基本的方式。从简单说起在所有的工厂模式中最简单的工厂模式应该就是使用Template Method的方式创建对象的实例。也有好多人认为这种方法还不能算是工厂模式,可是从其所起的本质的作用和实际运行机制来看应该可以也算作一种特殊形式的工厂模式。

 

具体的实现方法是:在目标类中增加一个方法,该方法的目的就是为了创建该对象或是该对象的抽象的实例。一般情况下为了便于使用把这个方法通常都被声明成静态的。

 

示例代码:

 

              public class Vehicle

 

              {

 

                  private Vehicle()

 

                  {

 

                       //

 

                       // TODO: 在此处添加构造函数逻辑

 

                       //

 

                  }

 

                  private void PrepareBehavior()

 

                  {

 

                       //初始化设置对象

 

                  }

 

                  /// <summary>

 

                  /// Template Method 负责创建Vehicle的实例

 

                  /// </summary>

 

                  /// <returns></returns>

 

                  public static Vehicle GetInstance()

 

                  {

 

                       Vehicle objVehicle = new Vehicle();

 

                       objVehicle.PrepareBehavior();

 

                       return objVehicle;

 

                  }

 

  }

 

上面代码就是一个最简单的应用,正如我在前面文章里设计模式-旧话重提之类工厂的使用所说的,利用这种方式可以把new 操作从业务逻辑类中脱离出来,解除业务逻辑类与Vehicle具体的类(type)之间的耦合。把在系统中创建对象的操作从业务逻辑类中脱离出来,改为使用一个单独的方法来完成,这样即使未来创建对象的过程发生改变,这种改变也和我们的业务逻辑编码无关,我们需要做的仅仅是修改这个方法的实现代码。在GetInstance()方法返回实例之前我们可以为这个实例做各种准备工作:可以修改一些状态、执行一些我们必要的方法,如果有需要我们甚至可以让GetInstance() 方法直接返回Vehicle 类的具体实现的子类型。而所有的这些实现都是密闭的,是和外部无关的。

 

在实际项目的应用中如果目标对象的继承体系比较简单、固定,功能比较单一,可能在未来发生的变化是比较容易预期到的,则可以考虑使用这种方法。

 

简单工厂模式  

 

一般是一个工厂类对应多个具体产品类,通过外界向工厂传递的参数来判断创建某一个具体的产品类

 

既然被叫做“工厂”当然不能只生产一样产品,简单工厂只生产同一家族的产品,具体的说就是简单工厂创建的类都是从同一个抽象继承下来的。根据客户不同的需求来创建不同的类,可是被创建的类都必须满足一个条件:必须是同一家族的产品(从同一个根继承下来的子类)。例如:有一个生产水果的简单工厂,根据客户的需要可以生产苹果、橘子、葡萄、香蕉,但是必须满足一个要求,就是它只能生产水果。如果客户需要机器、房屋等东西,那么这些要求都将不能被满足.

 

简单工厂结构简单,由三个部分构成:

 

类工厂 : 是最核心的部分,作为简单工厂对外使用的接口,负责实现创建实例的逻辑 。

 

抽象产品: 工厂生产所有的产品的抽象 ,可能是抽象类或接口,也可能是普通的基类。

 

具体产品: 简单工厂创建的具体类的实例 。

 

示例代码

 

Public Class Vehicle

 

{

 

 

 

}

 

Public Class Car : Vehicle

 

{

 

}

 

Public Class Train : Vehicle

 

{

 

}

 

Public class SimpleFactory

 

{

 

    Public Vehicle Create(string type)

 

{

 

    If (条件判断)

 

{

 

    Return new Car();

 

}

 

If (条件判断)

 

{

 

    Return new Train();

 

}

 

 

 

 

 

}

 

.其他判断条件

 

Return new Other();

 

}

 

 

 

在简单工厂结构的三部分中工厂类部分是重中之重,所有的核心功能都是靠工厂类实现的,如根据条件判断创建哪种具体的产品,以及实际创建产品等。在这一点上违背了“对象的职责均衡分布的原则”,因为功能过于集中在工厂类本身,随着简单工厂生产的产品种类的增加,使其业务逻辑无限的增加,会使其本身越来越复杂而难于维护和扩展。例如,如果增加产品,必须更改工厂类的代码逻辑。简单工厂比工厂方法和抽象工厂相比其优势是简单易用。只靠一个工厂类就可以创建所有的产品类,而缺点就是随着产品种类增加使其越来越难以使用。当工厂只生产同一品种的具体产品,而且产品数量有限的时候,可以考虑使用此工厂模式。

 

         Factory Method模式

 

       在工厂父类中定义一个标准的方法用来生产产品。一般来说这个方法应该被声明成抽象方法(当工厂父类是抽象类的时候),或接口中的空方法(工厂父类仅仅是接口),这个方法只有方法的定义并没有具体实现。将这个方法的具体实现延迟到子类中来完成。这样父类只需要负责取出抽象的产品,而不必关心怎么去创建具体的产品和到底创建哪一种具体的产品。至于究竟应该创建何种具体的产品由具体的子类负责决定。考虑到简单工厂模式中因为功能过于集中在工厂类中而产生的种种的缺陷,在Factory Method模式中把工厂类生产产品的定义和生产具体产品的实现拆分开,用一个类的继承体系来消除工厂类中复杂的逻辑判断语句。从而使类的职责、能力能够比较均衡的分布。

 

Factory Method结构由四个部分构成:

 

抽象类工厂 : 定义统一的接口来创建产品。

 

具体类工厂 :实现创建具体产品类的类工厂(一般为多个)。

 

抽象产品: 工厂生产所有产品的抽象 ,可能是抽象类或接口,也可能是普通的基类。

 

具体产品: Factory Method创建的具体类的实例(多个)。

 

示例代码

 

Public abstract  class  AbstractFactory

 

{

 

       Public abstract  Vehicle Create();

 

 

 

}

 

Public class CarFactory : AbstractFactory

 

{

 

       Public override Vehicle Create()

 

       {

 

              Return new Car();

 

       }

 

}

 

Public class Train Factory : AbstractFactory

 

{

 

       Public override Vehicle Create()

 

       {

 

              Return new Train ();

 

       }

 

}

 

 

 

       这样一来,客户端程序可以通过更改创建产品的工厂类的子类,用统一的方式创建不同的具体产品。即使需要增加生产新的产品也不需要修改现有的代码,只要创建一个生产这个产品的子工厂类就可以了。前提是这个新产品和原来工厂生产的产品必须是一类的(接口必须是一致的)。工厂方法模式的优势是:因为生产具体产品是靠子工厂类实现的,增加新的产品不会影响到现有的程序,从这点上来看程序是“闭合”的。修改子工厂类的实现方式也不会影响客户端的使用。同时它的局限也很明显,在工厂方法模式中因为所有的具体产品都是同一个父类(或接口)继承下来的,它只能生产“同一种类”的具体产品。比如上例:这个工厂只能生产各种类的 Vehicle   如果你需要食物、水果和电子产品的话,那么上面的工厂方法模式是不可能满足你的。还有因为在客户端调用此模式生产产品的时候是直接使用的子工厂类,如果需要修改生产产品的种类的话,则需要修改客户端的代码,这点有些不满足面向抽象的原则。如果要解决这种问题那就需要和别的设计模式结合起来使用。

 

         Abstract Factory模式

 

                上面讲的工厂模式并不能够生产不同种类的产品,为了解决这个问题,就需要使用Abstract Factory模式 。抽象工厂模式和工厂方法模式有了很大的不同。Abstract Factory模式的目的提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。使用抽象工厂创建的产品是“产品族”,也就是两族或两族以上的产品,并且这些产品是“相关”的、“相互依赖”的。如果只生产一族产品,抽象工厂模式就完全退化成了工厂方法模式。

 

所以抽象工厂使用的前提条件有两个:

 

1、生产产品族大于一族,只有生产两族以上的产品才使用抽象工厂。

 

2、产品之间有特殊的相关或依赖关系,产品之间应该最少应该有两种关系,纵向来看每种产品组内部产品之间有继承关系。例如:产品AbstractProductAProductA1ProductA2之间有继承关系是同一产品族产品。横向来看两个产品族之间的产品也应该有一一对应关系,例如:ProductA1ProductB1之间,或ProductA2ProductB2之间的对应关系。在只满足条件1的前提下,感觉应该使用多个工厂方法模式来代替抽象工厂模式,这样使用起来应该会方便一些。