研磨设计模式之工厂方法模式(Factory Method)-模式讲解1

2019-03-08 16:21|来源: 网络

3  模式讲解

3.1  认识工厂方法模式

(1)模式的功能
       工厂方法的主要功能是让父类在不知道具体实现的情况下,完成自身的功能调用,而具体的实现延迟到子类来实现。
       这样在设计的时候,不用去考虑具体的实现,需要某个对象,把它通过工厂方法返回就好了,在使用这些对象实现功能的时候还是通过接口来操作,这非常类似于IoC/DI的思想,这个在后面给大家稍详细点介绍一下。


(2)实现成抽象类
       工厂方法的实现中,通常父类会是一个抽象类,里面包含创建所需对象的抽象方法,这些抽象方法就是工厂方法。
       这里要注意一个问题,子类在实现这些抽象方法的时候,通常并不是真的由子类来实现具体的功能,而是在子类的方法里面做选择,选择具体的产品实现对象。
       父类里面,通常会有使用这些产品对象来实现一定的功能的方法,而且这些方法所实现的功能通常都是公共的功能,不管子类选择了何种具体的产品实现,这些方法的功能总是能正确执行。


(3)实现成具体的类
       当然也可以把父类实现成为一个具体的类,这种情况下,通常是在父类中提供获取所需对象的默认实现方法,这样就算没有具体的子类,也能够运行。
       通常这种情况还是需要具体的子类来决定具体要如何创建父类所需要的对象。也把这种情况称为工厂方法为子类提供了挂钩,通过工厂方法,可以让子类对象来覆盖父类的实现,从而提供更好的灵活性。


(4)工厂方法的参数和返回
       工厂方法的实现中,可能需要参数,以便决定到底选用哪一种具体的实现。也就是说通过在抽象方法里面传递参数,在子类实现的时候根据参数进行选择,看看究竟应该创建哪一个具体的实现对象。
       一般工厂方法返回的是被创建对象的接口对象,当然也可以是抽象类或者一个具体的类的实例。


(5)谁来使用工厂方法创建的对象
       这里首先要搞明白一件事情,就是谁在使用工厂方法创建的对象?
       事实上,在工厂方法模式里面,应该是Creator中的其它方法在使用工厂方法创建的对象,虽然也可以把工厂方法创建的对象直接提供给Creator外部使用,但工厂方法模式的本意,是由Creator对象内部的方法来使用工厂方法创建的对象,也就是说,工厂方法一般不提供给Creator外部使用。
       客户端应该是使用Creator对象,或者是使用由Creator创建出来的对象。对于客户端使用Creator对象,这个时候工厂方法创建的对象,是Creator中的某些方法使用。对于使用那些由Creator创建出来的对象,这个时候工厂方法创建的对象,是构成客户端需要的对象的一部分。分别举例来说明。


   ①客户端使用Creator对象的情况
       比如前面的示例,对于“实现导出数据的业务功能对象”的类ExportOperate,它有一个export的方法,在这个方法里面,需要使用具体的“导出的文件对象的接口对象” ExportFileApi,而ExportOperate是不知道具体的ExportFileApi实现的,那么怎么做的呢?就是定义了一个工厂方法,用来返回ExportFileApi的对象,然后export方法会使用这个工厂方法来获取它所需要的对象,然后执行功能。
       这个时候的客户端是怎么做的呢?这个时候客户端主要就是使用这个ExportOperate的实例来完成它想要完成的功能,也就是客户端使用Creator对象的情况,简单描述这种情况下的代码结构如下:

/**

* 客户端使用Creator对象的情况下,Creator的基本实现结构

*/

public abstract class Creator {

   /**

    * 工厂方法,一般不对外

    * @return 创建的产品对象

    */

   protected abstract Product factoryMethod();

   /**

    * 提供给外部使用的方法,

    * 客户端一般使用Creator提供的这些方法来完成所需要的功能

    */

   public void someOperation(){

      //在这里使用工厂方法

      Product p = factoryMethod();

   }

}

②客户端使用由Creator创建出来的对象
       另外一种是由Creator向客户端返回由“工厂方法创建的对象”来构建的对象,这个时候工厂方法创建的对象,是构成客户端需要的对象的一部分。简单描述这种情况下的代码结构如下:

/**

* 客户端使用Creator来创建客户端需要的对象的情况下,Creator的基本实现结构

*/

public abstract class Creator {

   /**

    * 工厂方法,一般不对外,创建一个部件对象

    * @return 创建的产品对象,一般是另一个产品对象的部件

    */

   protected abstract Product1 factoryMethod1();

   /**

    * 工厂方法,一般不对外,创建一个部件对象

    * @return 创建的产品对象,一般是另一个产品对象的部件

    */

   protected abstract Product2 factoryMethod2();

   /**

    * 创建客户端需要的对象,客户端主要使用产品对象来完成所需要的功能

    * @return 客户端需要的对象

    */

   public Product createProduct(){

      //在这里使用工厂方法,得到客户端所需对象的部件对象

      Product1 p1 = factoryMethod1();

      Product2 p2 = factoryMethod2();

      //工厂方法创建的对象是创建客户端对象所需要的

      Product p = new ConcreteProduct();

      p.setProduct1(p1);

      p.setProduct2(p2);

     

      return p;

   }

}

       小结一下:在工厂方法模式里面,客户端要么使用Creator对象,要么使用Creator创建的对象,一般客户端不直接使用工厂方法。当然也可以直接把工厂方法暴露给客户端操作,但是一般不这么做。


(6)工厂方法模式的调用顺序示意图
       由于客户端使用Creator对象有两种典型的情况,因此调用的顺序示意图也分做两种情况,先看看客户端使用由Creator创建出来的对象情况的调用顺序示意图,如图.5所示:


图5  客户端使用由Creator创建出来的对象的调用顺序示意图


接下来看看客户端使用Creator对象时候的调用顺序示意图,如图6所示:



图6  客户端使用Creator对象的调用顺序示意图

本文链接:研磨设计模式之工厂方法模式(Factory Method)-模式讲解1,转自:http://chjavach.iteye.com/blog/692792

相关问答

更多
  • 抽象工厂:比工厂模式更深一层,这回连工厂的实现类都不知道了,不同的人可以拿到不同的工厂类。所以抽象工厂类其实是一个做工厂的工厂类,可以产生出不同的工厂类。 简单的说如果把“用工厂生成对象”这层关系当做一级生成关系,那么抽象工厂方法就是拥有二级生成关系的工厂方法。如果实际环境更复杂,可以三级 甚至 四级,所以你别想的太复杂,就这么简单。 设计模式这本书写的不错,不过请启发性的看他,别深究,因为: 设计模式成书较早那个时候程序员对程序的理解还保持在代码能编译通过就好,所以你会发现有很多特性在现在看起来很白痴,似 ...
  • 这不是GOF创作模式。 它是抽象工厂模式的变体,有时称为参数化工厂模式 。 参数化工厂根据传递给create方法的参数(通常是Id或类型说明符)创建不同的对象。 你的例子中的GOF工厂方法就是这样的(只是一个例子......没有意义......) struct AreaCalculator { virtual double calculateArea() = 0; }; struct CircleCalculator { CircleCalculator(const Circle& cir ...
  • 最简单的方法是使用单个静态字段,并在已创建映射时返回该值。 代码未经测试,但我认为这个概念很简单: public class MapCreator{ private static Map theOnlyMap; public synchronized Map createMap(char mapType){ if( theOnlyMap != null ) return theOnlyMap; switch(mapType){ case ...
  • 我不确定工厂方法设计模式在函数式编程中的作用程度。 模式的目标是隐藏对象的创建,以便您可以仅使用对象的抽象表示。 当您以功能方式使用F#时,您将在大多数时间使用具体表示。 例如,这使您能够在滑板类型上进行模式匹配。 当然,F#允许您将功能风格与面向对象的风格相结合。 出于某些目的,OO风格在F#中运行良好。 在这种情况下,您的方法看起来很合理。 您的工厂方法可以采用具体类型(例如,区分联合)作为参数,而不是字符串。 然后工厂的任务是从具体表示构建抽象表示: // Abstract representatio ...
  • 工厂方法已修复 - 您无法在运行时更改它。 抽象工厂允许您使用不同工厂创建对象,这可以在运行时根据某些条件进行选择。 Button button = WinButtonFactory.create(); //will always be a "windows button" Button button = buttonFactory.create(); 像这样的第二个可以是WinButtonFactory extends ButtonFactory或者MacOSXButtonFactory extends ...
  • 为什么不把工厂组成为Creator类而不是用抽象方法表达它呢? 因为在这种情况下,客户端“知道”要实例化哪个Factory类,这会破坏模式的整体目的。 整个想法是,客户不知道什么是工厂,它只是调用一个Abstract类。 假设你将一些第三方工厂提供者插入到你的框架中,并且只要达到目的,你就不知道他们实例化了什么(也不关心)。 Why not composing the Factory into the Creator class instead of expressing it using an abstr ...
  • 使用工厂方法模式的优点是,您可以将类的创建的业务逻辑与类的实际逻辑分离,因为如果您没有该工厂方法,那么您在系统上添加的每个类都需要具有内部的工厂方法,当你必须改变一些关于创建的东西时,你可能必须处理所有这些类(对于开放封闭原则不利) The advantage of using the factory method pattern is that you decouple the business logic of creation of a class from the actual logic of t ...
  • 我知道工厂方法模式有更多我缺少的东西但是依靠继承的优势组合,我找到了以下方法,在同一场景中解决同样的问题 使用Factory Method模式而不是普通旧组合时,您可以获得以下几个优点: 1.关注点分离和开放原则 :为每个相关的对象组创建一个工厂子类。 此工厂子类仅负责创建属于特定组的那些产品。 ABCProductFactory只关注创建ABCProduct1 , ABCProduct2等CDEProductFactory只关注创建CDEProduct1 , CDEProduct2等。 对于每个新产品组, ...
  • 遗憾的是,您正在阅读的链接并未提供该模式的实际示例。 实际上,根据原始的GoF设计模式,这种模式称为抽象工厂 (工厂方法是一种不同的模式)。 当您拥有可以创建一系列对象的工厂时,将使用抽象工厂模式。 例如,你可以拥有和AbstractGUIFactory ,它可以有方法createButton(), createWindow(), createTitleBar等。然后,你将拥有像WindowsGUIFactory, MacGUIFactory, MotifGUIFactory等具体的工厂,每个工厂都会产生B ...
  • 工厂的基本思想是函数返回从已知基类派生的堆分配对象。 因此,在你的情况下,你可能会在你的主应用程序中有一些代码调用dll中的工厂,找回未知动态类型和实现的对象,但你会知道它满足特定基类的API要求。 然后通过该接口使用该对象,并通过其大概的虚拟析构函数将其删除。 取决于实际派生类的选择方式,工厂方法有多种类型,但通常它会检查函数的一些输入,IO流或XML结构等,并计算出适当的类型。 工厂是否在dll中对这里的整体模型没有什么影响,但它确实可以更容易地更新派生对象的列表和实现,而无需重新编译应用程序。 有关更 ...