1. 定义

定义一个用于创建对象的接口,让工厂类决定实例化哪一个生产类。

工厂方法使一个生产类的实例化,延迟到对应的工厂子类中。

一个生产类,都有一个与之对应的工厂类

2. 解读

类比:

  • 工厂方法模式中的工厂较简单工厂模式中的工厂有明显的区别。简单工厂模式中的工厂类,像一个综合工厂,大而全,可以生产各种各样的产品;而工厂方法模式中的工厂,小而美,每个工厂仅生产一种产品。

解析:

  • 工厂方法模式是简单工厂模式的改进版,当生产类增加时,无需修改已有的工厂类,而是新增工厂类,符合开放-封闭原则
  • 但仔细观察会发现,工厂方法模式将实例化的判断转移到了客户端,选择判断的问题还是存在的。若想增加新功能,简单工厂模式是更改工厂类,在工厂方法模式中是需要改动客户端。
  • 使用反射机制,用动态编程的方式可以解决客户端判断的问题。也即,使用哪个工厂的场景写到配置文件中,程序运行时通过读取配置文件,动态选择所需要的逻辑。

要点:

  1. 抽象生产类接口
  2. 抽象工厂类接口
  3. 工厂类是实例化生产类的唯一位置

3. 举例

抽象工厂类,每一个生产类,都对应一个工厂类,工厂类是实例化生产类的唯一位置。
在这里插入图片描述

3.1 工厂接口与工厂类的实现

REPORT zfactory_method_pattern.
**********************************************************************
*1) Extract productive interface
*2) Extract factory interface
*3) Each concrete class has its factory class
*4) Factory is the only place to create a productive instance
*5) When new product class is added, a corresponding factory is also
*   added, open-close principle
**********************************************************************
INTERFACE lif_product.
  METHODS get_name
    RETURNING
      VALUE(rv_name) TYPE string.
  METHODS notify_customer.
ENDINTERFACE.

INTERFACE lif_product_factory.
  METHODS create
    RETURNING
      VALUE(ro_product) TYPE REF TO lif_product.
ENDINTERFACE.
**********************************************************************
CLASS lcf_product_a DEFINITION DEFERRED.
CLASS lcf_product_b DEFINITION DEFERRED.
**********************************************************************
CLASS lcl_product_a DEFINITION FINAL CREATE PRIVATE
FRIENDS lcf_product_a.
  PUBLIC SECTION.
    INTERFACES lif_product.
ENDCLASS.

CLASS lcl_product_a IMPLEMENTATION.
  METHOD lif_product~get_name.
    rv_name = 'Product A'.
  ENDMETHOD.

  METHOD lif_product~notify_customer.
    WRITE: / 'We are delivering: ' && me->lif_product~get_name(  ).
  ENDMETHOD.
ENDCLASS.

CLASS lcl_product_b DEFINITION FINAL CREATE PUBLIC
FRIENDS lcf_product_b.
  PUBLIC SECTION.
    INTERFACES lif_product.
ENDCLASS.

CLASS lcl_product_b IMPLEMENTATION.
  METHOD lif_product~get_name.
    rv_name = 'Product B'.
  ENDMETHOD.

  METHOD lif_product~notify_customer.
    WRITE: / 'We are delivering: ' && me->lif_product~get_name(  ).
  ENDMETHOD.
ENDCLASS.
**********************************************************************
CLASS lcf_product_a DEFINITION FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES lif_product_factory.
ENDCLASS.

CLASS lcf_product_a IMPLEMENTATION.
  METHOD lif_product_factory~create.
    ro_product = NEW lcl_product_a(  ).
  ENDMETHOD.
ENDCLASS.

CLASS lcf_product_b DEFINITION FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES lif_product_factory.
ENDCLASS.

CLASS lcf_product_b IMPLEMENTATION.
  METHOD lif_product_factory~create.
    ro_product = NEW lcl_product_b(  ).
  ENDMETHOD.
ENDCLASS.
**********************************************************************
START-OF-SELECTION.
  DATA(lo_product_a_factory) = NEW lcf_product_a(  ).
  DATA(lo_product_b_factory) = NEW lcf_product_b(  ).
  DATA(lo_product_a) = lo_product_a_factory->lif_product_factory~create(  ).
  DATA(lo_product_b) = lo_product_b_factory->lif_product_factory~create(  ).

  lo_product_a->notify_customer(  ).
  lo_product_b->notify_customer(  ).

在此例中,可以看到与客户端交互的仅有工厂类,工厂类实现类封装和隔离的功能,生产类的变更,不会影响客户端的改动。

运行结果:
在这里插入图片描述

3.2 动态调用工厂类

在ABAP中,可以通过动态编程的方式,来根据配置来选择工厂类。也即,可以将变化从代码转移至配置文件,当功能变更时,只需改动相关的配置文件即可。

**********************************************************************
START-OF-SELECTION.

  " to create product dynamically by factory,
  " the product is changed according to its dynamic factory
  DATA lo_product_factory TYPE REF TO lif_product_factory.
  DATA lv_factory_name TYPE seoclsname VALUE 'LCF_PRODUCT_A'.

  CREATE OBJECT lo_product_factory TYPE (lv_factory_name).
  DATA(lo_product) = lo_product_factory->create(  ).
  lo_product->notify_customer(  ).

在此例中,客户端对于工厂方法的调用时动态的,这种方式进一步提高了客户端代码的灵活性,可配置性。

以上是对工厂方法模式的总结,欢迎分享、留言。😉

本博客专注于技术分享,干货满满,持续更新。
欢迎关注❤️、点赞👍、转发📣!

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐