ABAP设计模式之---“建造者模式(Builder Pattern)”

1.目的

将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程,可以创建不同的表示。

2.解读

类比:

  • 建造者模式类似于模拟现实世界中供应商组装厂的关系。什么意思呢?举个栗子 😉
  • 手机的生产过程其实就是一个很好的例子。一个手机“对象”是很复杂的,但如果不同的角色如果分工合作,扬长避短,那么就会极大降低手机生产的复杂度。也即,品牌厂商仅负责手机的设计工作,而手机的零件可以从不同的供应商采购,最终由代工厂完成手机组装。手机厂商零件供应商代工厂就是我们“建造者模式”的主角。

解析:

  • 这个模式相对复杂,但不要被不同的角色所迷惑,“建造者模式” 的最终目的也是要产出一个类实例,只不过是将实例化的过程按照“职责”进行了进一步的分工
  • 适用于复杂对象的构建,也即目标类的实例化过程很复杂
  • 其实,一定程度上简化“建造者模式”的中角色也是可以的,划分不同角色,是为了更好地符合单一职责原则,并提升类的灵活性

各种角色:

  1. Product - 产品对象,也即我们最终想实例化的对象 (手机)
  2. Abstract Builder - 抽象建造者,为Product的形成提供各种部件方法(例如采购芯片、采购屏幕、采购电池等)
  3. Concrete Builder - 具体建造者,实现Abstract Builder,构造和装配各个具体的部件(例如,使用高通的芯片,夏普的屏幕,Sony的电池等等)
  4. Director - 指挥者,定义了建造的流程(例如先在主板上焊接芯片,然后连接屏幕,主板完成后,连接电池)

要点:

  1. “建造者模式” 的优点在于,其隐藏了某产品对象是如何组装的,若需要改变一个产品的内部表示,只需要在定义一个具体的建造者就可以了。
  2. 还是以手机的例子,如果生产另一种型号的手机,使用联发科芯片,京东方的屏幕,三星的电池,那么此时有另一个实现这些部件方法的建造者即可。手机的组装流程依然是标准的,也即先在焊接芯片,然后连接屏幕,最后连接电池。
  3. 由此可见,此模式适合这种对象内部构件的顺序稳定,但对象内部的表现有着复杂变化的对象

体现的设计原则:

简化建造者模式:

  • “建造者模式好复杂,不用建造者模式,行不行?” 哈哈,当然可以的。如果不使用建造者模式,那么意味值客户端要自己构建和实例化Prodcut类,从零开始建造。看到区别了么?一种是给客户一个“手机”图纸,让客户自己去买配件,做“手机”;而建造者模式是把“手机”制造好后,给客户使用。
  • “省略Builder和Director,直接使用工厂方法模式给客户生产手机OK么?” 这样当然可以啦,客户可以通过工厂方法直接拿到手机,工厂方法中负责手机零件和购买和组装。但这种方式的问题是什么呢?如果是生产一个手机模型,工厂方法应该是能够胜任的,因为这个产品足够简单。但要是生成真正的手机,工厂方法承担的职责就太重了,“建造者模式中”的Builder和Director可以把工厂方法解放出来,进一步Product实例化的灵活性。

3.举例

3.1 类图

客户端指定建造者Builder和建造流程Director,就可以拿到一个产成品啦。
在这里插入图片描述

3.2 代码实现

在示例代码中,我们通过两个不同的建造者,依据同一套流程,分别生成产品。

REPORT zbuilder_pattern.
**********************************************************************
* Product
**********************************************************************
CLASS lcl_product DEFINITION FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS:
      set_part_a
        IMPORTING iv_part_a TYPE string,
      set_part_b
        IMPORTING iv_part_b TYPE string,
      set_part_c
        IMPORTING iv_part_c TYPE string,
      display.

  PRIVATE SECTION.
    DATA mv_part_a TYPE string.
    DATA mv_part_b TYPE string.
    DATA mv_part_c TYPE string.
ENDCLASS.

CLASS lcl_product IMPLEMENTATION.
  METHOD set_part_a.
    mv_part_a = iv_part_a.
  ENDMETHOD.

  METHOD set_part_b.
    mv_part_b = iv_part_b.
  ENDMETHOD.

  METHOD set_part_c.
    mv_part_c = iv_part_c.
  ENDMETHOD.

  METHOD display.
    WRITE: / 'This prodcut contains 3 part:'.
    WRITE: / 'The frist part is:' && mv_part_a.
    WRITE: / 'The second part is:' && mv_part_b.
    WRITE: / 'The third part is:' && mv_part_c.
  ENDMETHOD.
ENDCLASS.
**********************************************************************
* Builder
**********************************************************************
INTERFACE lif_builder.
  METHODS:
    build_part_a,
    build_part_b,
    build_part_c,
    get_result
      RETURNING
        VALUE(ro_product) TYPE REF TO lcl_product.
ENDINTERFACE.

CLASS lcl_builder_1 DEFINITION FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS constructor.
    INTERFACES lif_builder.

  PRIVATE SECTION.
    DATA mo_product TYPE REF TO lcl_product.
ENDCLASS.

CLASS lcl_builder_1 IMPLEMENTATION.
  METHOD constructor.
    mo_product = NEW #( ).
  ENDMETHOD.

  METHOD lif_builder~build_part_a.
    mo_product->set_part_a( 'Part A' ).
  ENDMETHOD.

  METHOD lif_builder~build_part_b.
    mo_product->set_part_b( 'Part B' ).
  ENDMETHOD.

  METHOD lif_builder~build_part_c.
    mo_product->set_part_c( 'Part C' ).
  ENDMETHOD.

  METHOD lif_builder~get_result.
    ro_product = mo_product.
  ENDMETHOD.
ENDCLASS.
**********************************************************************
CLASS lcl_builder_2 DEFINITION FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS constructor.
    INTERFACES lif_builder.

  PRIVATE SECTION.
    DATA mo_product TYPE REF TO lcl_product.
ENDCLASS.

CLASS lcl_builder_2 IMPLEMENTATION.
  METHOD constructor.
    mo_product = NEW #( ).
  ENDMETHOD.

  METHOD lif_builder~build_part_a.
    mo_product->set_part_a( 'Part X' ).
  ENDMETHOD.

  METHOD lif_builder~build_part_b.
    mo_product->set_part_b( 'Part Y' ).
  ENDMETHOD.

  METHOD lif_builder~build_part_c.
    mo_product->set_part_c( 'Part Z' ).
  ENDMETHOD.

  METHOD lif_builder~get_result.
    ro_product = mo_product.
  ENDMETHOD.
ENDCLASS.
**********************************************************************
* Director
**********************************************************************
CLASS lcl_director DEFINITION FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS construct
      IMPORTING
        io_builder        TYPE REF TO lif_builder
      RETURNING
        VALUE(ro_product) TYPE REF TO lcl_product.
ENDCLASS.

CLASS lcl_director IMPLEMENTATION.
  METHOD construct.
    io_builder->build_part_a(  ).
    io_builder->build_part_b(  ).
    io_builder->build_part_c(  ).
    ro_product = io_builder->get_result(  ).
  ENDMETHOD.
ENDCLASS.
**********************************************************************
START-OF-SELECTION.
  DATA(lo_director) = NEW lcl_director(  ).
  DATA(lo_builder_1) = NEW lcl_builder_1(  ).
  DATA(lo_builder_2) = NEW lcl_builder_2(  ).

  DATA(lo_prodcut_1) = lo_director->construct( lo_builder_1 ).
  DATA(lo_prodcut_2) = lo_director->construct( lo_builder_2 ).

  lo_prodcut_1->display(  ).
  lo_prodcut_2->display(  ).

运行结果:
在这里插入图片描述
以上是对建造者模式的总结,欢迎分享、留言。😉

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十年铸器

给作者赏杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值