在原文基础上整理了一下,并做了测试,代码可运行。
原文地址: http://tech.sina.com.cn/s/2009-08-07/10501017671.shtml
内容:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
简单来说,工厂方法模式能够封装具体的类型的实例化。
结构:
Product:所有产品都必须实现这个共同的接口,这样一来,使用这些产品的类就可以引用这个接口,而不是具体类。
ConcreteCreator:负责创建一个或者多个具体产品,只有concrete creator类知道如何创建这些产品。同时,它实现了factory method,以实际制造出产品。
Creator: 是一个抽象类,它实现了所有操作产品的方法,但不实现工厂方法。其所有的子类都必须实现这个抽象的factorymethod()方法。
实例程序,首先给出类图:
注意:创建类和产品类是平行的,因为他们都是抽象类,而抽象类都有许多具体的子类,每个子类都有自己特定的实现。
测试程序如下:
REPORT zgary_t007.
INCLUDE zgary_t007_class_define.
*This data used to create two type of concrete creator
DATA: ny_ref TYPE REF TO pizzastore,
chi_ref TYPE REF TO pizzastore.
*the different pizza have the same interface
DATA: pz_ref TYPE REF TO pizza.
START-OF-SELECTION.
* Create two different pizzastore
CREATE OBJECT ny_ref TYPE ny. "For NY
CREATE OBJECT chi_ref TYPE chi."For Chi
* Book NY store's pizza
CALL METHOD ny_ref->orderpizza
EXPORTING
pz_name1 = 'CHEESE'
RECEIVING
pz = pz_ref.
* Get the pizza's name
DATA: ls TYPE string.
CALL METHOD pz_ref->getname
RECEIVING
na = ls.
WRITE: / 'Ethan ordered a:',ls.
SKIP.
* Book Chi store's pizza
CALL METHOD chi_ref->orderpizza
EXPORTING
pz_name1 = 'CHEESE'
RECEIVING
pz = pz_ref.
* Get the pizza's name
CALL METHOD pz_ref->getname
RECEIVING
na = ls.
WRITE: / 'Joel ordered a:', ls.
*&---------------------------------------------------------------------*
*& Include ZGARY_T007_CLASS_DEFINE
*&---------------------------------------------------------------------*
*抽象产品类:
*declare product class
CLASS pizza DEFINITION ABSTRACT.
PUBLIC SECTION.
* define instance variants
DATA: name TYPE string,
dough TYPE string,
sauce TYPE string.
DATA: BEGIN OF rtab,
str TYPE string,
END OF rtab,
itab LIKE TABLE OF rtab.
* methods which will be inherited by subclass
METHODS:
prepare, " prepare pizza
bake, " bake pizza
cut, " cut pizza
box, " boxing pizza
getname " getter method to get pizza name
RETURNING value(na) TYPE string.
ENDCLASS. "
*implement the pizza class
CLASS pizza IMPLEMENTATION.
METHOD prepare.
WRITE: / 'Preparing:', name,
/ 'Tossing dough....',
/ 'Adding sauce....',
/ 'Adding toppings:'.
LOOP AT itab INTO rtab.
WRITE: / rtab-str.
ENDLOOP.
ENDMETHOD. "prepare
METHOD bake.
WRITE: / 'Bake for 25 minutes at 350'.
ENDMETHOD. "bake
METHOD cut.
WRITE: / 'Cutting the pizza into diagonal slices'.
ENDMETHOD. "cut
METHOD box.
WRITE: / 'place pizza in official PizzaStore box'.
ENDMETHOD. "box
METHOD getname.
na = name.
ENDMETHOD. "getname
ENDCLASS. "
*工厂类:
*delare plant method class
*we can now define plant class, note that it is in the same leve as produ
CLASS pizzastore DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS:
orderpizza " this method is used to order the concrete product
IMPORTING pz_name1 TYPE string
RETURNING value(pz) TYPE REF TO pizza.
PROTECTED SECTION.
METHODS:
"this method seems LIKE a factory
"because this method is ABSTRACT, the subclass must instantiate thi
"this method must have a return value, which is the concrete produc
createpizza ABSTRACT
IMPORTING pz_name2 TYPE string
RETURNING value(pz) TYPE REF TO pizza.
ENDCLASS. "
*----------------------------------------------------------------------*
* CLASS pizzastore IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS pizzastore IMPLEMENTATION.
METHOD orderpizza.
DATA: pz_ref TYPE REF TO pizza.
"this is the key part of factory method pattern
"we use factory method to create concrete product
CALL METHOD createpizza
EXPORTING
pz_name2 = pz_name1
RECEIVING
pz = pz_ref.
" other methods
CALL METHOD:
pz_ref->prepare,
pz_ref->bake,
pz_ref->cut,
pz_ref->box.
" return the concrete product which have been created
pz = pz_ref.
ENDMETHOD. "orderpizza
ENDCLASS. "pizzastore IMPLEMENTATION
*具体产品类:
*ok, now we can concrete product
CLASS nystylepizza1 DEFINITION
INHERITING FROM pizza.
PUBLIC SECTION.
METHODS:
constructor.
ENDCLASS. "pizzastore IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS nystylepizza1 IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS nystylepizza1 IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor.
name = 'NY style Sauce and Cheese Pizza'.
dough = 'Thin Crust Dough'.
sauce = 'Marinara Sauce'.
rtab-str = 'Grated Reggiano Cheese'.
APPEND rtab TO itab.
ENDMETHOD. "constructor
ENDCLASS. "nystylepizza1 IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS chistylepizza1 DEFINITIO
*----------------------------------------------------------------------*
CLASS chistylepizza1 DEFINITION
INHERITING FROM pizza.
PUBLIC SECTION.
METHODS:
constructor,
cut REDEFINITION.
ENDCLASS. "chistylepizza1 DEFINITIO
*----------------------------------------------------------------------*
* CLASS chistylepizza1 IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS chistylepizza1 IMPLEMENTATION.
METHOD constructor.
CALL METHOD super->constructor.
name = 'Chicago Style Deep Dish Cheese Pizza'.
dough = 'Extra Thick Crust Dough'.
sauce = 'Plum Tomato Sauce'.
rtab-str = 'Shredded Mozzarella Cheese'.
APPEND rtab TO itab.
ENDMETHOD. "constructor
METHOD cut.
WRITE: / 'Cutting the pizza into square slices'.
ENDMETHOD. "cut
ENDCLASS. "chistylepizza1 IMPLEMENTATION
*具体创建类:
*now we can define the concrete creator
CLASS ny DEFINITION INHERITING FROM pizzastore.
PROTECTED SECTION.
METHODS:
createpizza REDEFINITION.
ENDCLASS. "chistylepizza1 IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS ny IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS ny IMPLEMENTATION.
METHOD createpizza.
CASE pz_name2.
WHEN 'CHEESE'.
CREATE OBJECT pz TYPE nystylepizza1.
WHEN 'VEGIE'.
WHEN 'CLAM'.
WHEN 'PEPPERONI'.
ENDCASE.
ENDMETHOD. "createpizza
ENDCLASS. "ny IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS chi DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS chi DEFINITION INHERITING FROM pizzastore.
PROTECTED SECTION.
METHODS:
createpizza REDEFINITION.
ENDCLASS. "chi DEFINITION
*----------------------------------------------------------------------*
* CLASS chi IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS chi IMPLEMENTATION.
METHOD createpizza.
CASE pz_name2.
WHEN 'CHEESE'.
CREATE OBJECT pz TYPE chistylepizza1.
WHEN 'VEGIE'.
WHEN 'CLAM'.
WHEN 'PEPPERONI'.
ENDCASE.
ENDMETHOD. "createpizza
ENDCLASS. "chi IMPLEMENTATION
程序运行结果: