ABAP面向对象之原型模式(Prototype Pattern)

149 阅读3分钟

概述

已经实例化了一个对象。而您的对象现在处于您希望从中复制自身的状态。换句话说,您想要克隆对象。如果您只是将对象引用分配给使用类似类型声明的另一个变量,因为这些是对象引用而不是实际数据。因此,您需要做的是实例化一个新对象并复制所有属性。

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

应用实例

1、细胞分裂。
2、JAVA 中的 Object clone() 方法。

优点

  1. 性能提高。
  2. 逃避构造函数的约束。

缺点

  1. 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
  2. 必须实现 Cloneable 接口。

使用场景

  1. 资源优化场景。
  2. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  3. 性能和安全要求的场景。
  4. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  5. 一个对象多个修改者的场景。
  6. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
  7. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。

注意事项:与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。

实现

我们将创建一个抽象类 CL_Shape 和扩展了 CL_Shape 类的实体类。下一步是定义类 CL_Shape_Cache,该类把 CL_shape 对象存储在一个 Hashtable 中,并在请求的时候返回它们的克隆。

UML:

图片

1. 创建一个实现了 Cloneable 接口的类。

INTERFACE if_cloneable.
  METHODS clone
    RETURNING VALUE(ro_instance) TYPE REF TO if_cloneable.
ENDINTERFACE.

CLASS cl_shape DEFINITION.
  PUBLIC SECTION.
    INTERFACES if_cloneable.

    METHODS:draw.

    METHODS:get_type
      RETURNING VALUE(rv_type) TYPE string.

    METHODS:get_id
      RETURNING VALUE(rv_id) TYPE string.

    METHODS:set_id
      IMPORTING iv_id TYPE string.

  PROTECTED SECTION.
    DATA:mv_type TYPE string.
  PRIVATE SECTION.
    DATA:mv_id   TYPE string.
ENDCLASS.


CLASS cl_shape IMPLEMENTATION.

  METHOD if_cloneable~clone.
    DATA(lo_shape) = NEW cl_shape( ).
    lo_shape->mv_id = mv_id .
    lo_shape->mv_type = mv_type.
    ro_instance = lo_shape.
  ENDMETHOD.

  METHOD draw.

  ENDMETHOD.

  METHOD get_type.
    rv_type  = mv_type.
  ENDMETHOD.

  METHOD get_id.
    rv_id  = mv_id.
  ENDMETHOD.

  METHOD set_id.
    mv_id = iv_id.
  ENDMETHOD.
ENDCLASS.

2. 创建扩展了上面抽象类的实体类。

CLASS cl_rectangle DEFINITION INHERITING FROM cl_shape.
  PUBLIC SECTION.
    METHODS constructor.
    METHODS draw REDEFINITION.
ENDCLASS.

CLASS cl_rectangle IMPLEMENTATION.
  METHOD constructor.
    super->constructor( ).
    me->mv_type = 'Rectangle'.
  ENDMETHOD.

  METHOD draw.
    WRITE:/ 'Inside CL_Rectangle->draw() method.'.
  ENDMETHOD.
ENDCLASS.


CLASS cl_square  DEFINITION INHERITING FROM cl_shape.
  PUBLIC SECTION.
    METHODS constructor.
    METHODS draw REDEFINITION.
ENDCLASS.

CLASS cl_square  IMPLEMENTATION.
  METHOD constructor.
    super->constructor( ).
    me->mv_type = 'Square '.
  ENDMETHOD.

  METHOD draw.
    WRITE:/ 'Inside CL_Square->draw() method.'.
  ENDMETHOD.
ENDCLASS.


3. 创建一个类,从数据库获取实体类,并把它们存储在一个 Hashtable 中。

CLASS cl_shape_cache DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:get_shape
      IMPORTING
                iv_id              TYPE string
      RETURNING VALUE(ro_instance) TYPE REF TO cl_shape.

    CLASS-METHODS load_cache
      .

  PRIVATE SECTION.
    TYPES:BEGIN OF ty_hash_table,
            id    TYPE string,
            shape TYPE REF TO cl_shape,
          END OF ty_hash_table.

    CLASS-DATA:mt_hash_table TYPE TABLE OF ty_hash_table .
ENDCLASS.

CLASS cl_shape_cache IMPLEMENTATION.
  METHOD get_shape.
    READ TABLE mt_hash_table INTO DATA(ls_hash_table) WITH KEY id = iv_id.
    ro_instance ?= ls_hash_table-shape->if_cloneable~clone( ).
  ENDMETHOD.

  METHOD load_cache.

    DATA(lo_rectangle) = NEW cl_rectangle( ).
    lo_rectangle->set_id('1').
    mt_hash_table = VALUE #( BASE mt_hash_table ( id = lo_rectangle->get_id( ) shape = lo_rectangle ) ).

    DATA(lo_square) = NEW cl_square( ).
    lo_square->set_id('2').
    mt_hash_table = VALUE #( BASE mt_hash_table ( id = lo_square->get_id( ) shape = lo_square ) ).
  ENDMETHOD.

ENDCLASS.

4.写个主程序执行

CLASS cl_application DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:  run .
ENDCLASS.


CLASS cl_application IMPLEMENTATION.
  METHOD run.
    cl_shape_cache=>load_cache( ).
    DATA(lo_cloned_shape1) = cl_shape_cache=>get_shape( '1' ).
    WRITE:/ 'Shape : ' ,lo_cloned_shape1->get_type( ).

    DATA(lo_cloned_shape2) = cl_shape_cache=>get_shape( '2' ).
    WRITE:/ 'Shape : ' ,lo_cloned_shape2->get_type( ).
  ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
  cl_application=>run(  ).

5.执行程序,输出结果

图片