1. 程式人生 > >6.3 SAP ABAP 開放封閉原則(OCP)- 摘自 《SAP ABAP面向對象程序設計:原則、模式及實踐》

6.3 SAP ABAP 開放封閉原則(OCP)- 摘自 《SAP ABAP面向對象程序設計:原則、模式及實踐》

selection douban 類工廠 ext 系統管理 oop 不可 行數 github

6.3 開放封閉原則(OCP)

開閉原則(Open-Closed Principle, OCP)指的是,一個類或者模塊,如果在業務修改或者功能需要擴展時,應盡可能保證只通過新添加代碼,而不是修改原有代碼的情況下完成。

該原則是Eiffel 語言的設計者,法國計算機科學家Meyer提出的,最開始的描述是:當向模塊添加字段或方法時,不可避免地需要對調用這個模塊的程序進行修改,解決這問題的方法是采用依賴於面向對象繼承(特別是從實際父類進行的實現繼承)的方法,而不是直接修改原來的程序。

從20世紀90年代開始,OCP的原則依然被大家遵循,只是解決的方式變了。隨著抽象類和接口等方式的大量應用,開放封閉原則開始提倡采用抽象類或接口的方法,而不是實現繼承來解決問題。

解決方式是現存的接口或抽象類對於修改原有的方法和屬性是封閉的,但對新添加的方法和屬性則是開放和允許的。

為什麽要對原有的代碼進行保護,對新加的代碼開放呢?

所有的軟件和程序都有一個生命周期,當需求和業務發生擴展和更新時,需要更新軟件(修復缺陷和軟件重構時的更新除外),要盡可能保證軟件的基本框架不變,盡可能不修改現有的代碼,而是添加新的實現代碼,使得軟件具有好的穩定性和可維護性。

實現擴展而不修改原有代碼的基礎就是采用接口或者抽象類等機制完成的。經過良好的定義,系統可以擁有一個相對穩定的抽象層,將業務行為下沈到具體的實現層中。

如果業務有擴展,可以將擴展的業務放到實現層中,只添加新的代碼,不修改已有的代碼,通過抽象層,將新的業務邏輯指定到新添加的業務實現層中。

如果業務有修改,無須對抽象層進行任何改動,添加實現代碼,替換固定的實現層代碼,而不會影響實現層其他模塊的行為。

設計實例:

一個公司中有多種物料類型,每種物料都要根據物料類型打印不同的檢驗說明單據,這個檢驗說明是由一個非面向對象的程序來控制的,當公司中的物料類型增加一種時,IT部門就被要求為這個程序添加一種打印方法。IT部門每次修改這個打印程序後,都要為以前的每一種的打印都做一個回退測試,保證新加的代碼沒有影響以往的業務。

如圖6-4所示,程序流程圖如下,當添加一種新物料類型時,程序就又多一組判斷:

技術分享圖片

技術分享圖片

代碼如示例程序6.1所示。

"示例程序6.1

REPORT zrep_cls_021.

DATA gv_material_type TYPE mara-mtart.
DATA gv_material TYPE mara-matnr.

PARAMETERS: p_matnr LIKE mara-matnr.

START-OF-SELECTION.

SELECT SINGLE mtart FROM mara INTO gv_material_type
WHERE matnr = p_matnr.

IF sy-subrc = 0.

"

類型判斷
IF ( gv_material_type EQ ‘ROH‘) .
WRITE: / ‘此物料為原料,需檢查采購合同 ‘.
ELSEIF ( gv_material_type EQ ‘FERT‘) .
WRITE: / ‘此物料為成品,需檢查銷售合同 ‘.
ENDIF.
ENDIF.

當每次公司出現一個新的物料類型時,就要添加一個針對這個新類型的相關檢驗的要求,我們就需要去修改這個IF ELSE代碼添加一個新的邏輯,主程序就要每一次都進行修改,這就不符合開放封閉原則。

對於不斷變化的業務,如果我們每次修改原有的代碼,除了要對增加的功能進行測試,對原有的功能還必須要做回退測試(Regression Test),保證新的邏輯沒有影響以前的業務邏輯。但如果軟件能夠做到僅增加新的代碼,不修改,或基於一定的規則的修改原有代碼,這樣就能保證工作量和代碼出錯的幾率大幅下降。這就是"開放-關閉"原則,即軟件擴展時只添加新代碼而不是修改原有代碼。

我們用面向對象的程序設計,並采用一個"改進的簡單工廠" 設計模式(也就是基於配置表的簡單工廠模式,具體結構見第7章第3節)來對系統進行重構,說明一下如何做到重構中的開放封閉原則。(例子中的這個程序因為太簡單,其實是沒必要進行面向對象重構的,但這個例子是足夠能說明實際業務中的重構過程和如何做到的遵循開放封閉原則。重構後,代碼量會增加,但卻是十分值得的。)

如圖6-5所示,首先將業務抽象為三層,第一層為物料對象生成工廠類,相當於主程序中的操作者,用於創建物料類的對象實例。第二層為抽象的物料類,由物料對象生成工廠類直接調用。第三層是具體的物料類,代表具體的物料類型,可以不斷從抽象類中繼承和添加新的子類,具體的解釋如表6-2所示。

其中第二層抽象類隔離開了操作類和具體物料類,使得主程序可以不必修改,就可以處理新添加的業務邏輯。

技術分享圖片

程序和實體列表

解釋

第一層類:物料對象生成工廠類

一個類,用於創建(生產)物料類的對象實例。

第二層抽象類:抽象的物料類

一個類,抽象的物料類。

第三層類:具體的物料類

可以有多個類,每個代表一個具體的物料類型和相應的處理方法。

數據表:物料類型和相應具體物理類的表

表中記錄了SAP物料的類型和對應具體類的類名。

技術分享圖片

技術分享圖片

我們逐步介紹如何創建這些類和實體:

第一步,如圖6-6所示,創建抽象的物料類ZCL_MATERIAL,這是第二層的抽象類,將多樣的具體業務抽象為一種模式。設定類的類型為"Abstract"抽象類。

技術分享圖片

技術分享圖片

如圖6-7所示,創建一個屬性MV_MATERIAL,為受保護可見度, 類型為物料號碼(MARA-MATNR)。

技術分享圖片

技術分享圖片

如圖6-8所示,設定方法PRINT_INSP_DESC,可見類型為Public,無參數。不必定義具體邏輯,該方法表明了物料類擁有打印檢驗說明的能力,但具體實現代碼是由其子類各自實現的。

技術分享圖片

技術分享圖片

第二步,如圖6-9所示,創建第三層的抽象的子類。分別為"成品物料類"ZCL_MATERIAL_FIN,"原料物料類"ZCL_MATERIAL_RAW,這一層是最底層的實現類,代表了具體的實現方法,如果有新的業務添加時,也是在這一層次創建新的類。

創建成品物料類ZCL_MATERIAL_FIN,從抽象物料類繼承。

技術分享圖片

技術分享圖片

如圖6-10所示,子類自動繼承屬性MV_MATERIAL,為受保護可見度, 類型為物料號碼。MARA-MATNR。

技術分享圖片

技術分享圖片

如圖6-11所示,重定義繼承來的方法PRINT_INSP_DESC。

技術分享圖片

技術分享圖片

如圖6-12所示,該方法是對應的成品物料類的具體操作方法,比如獲取固定數據,生成固定格式,並發送到相應的輸出打印機等。我們這裏就簡單的寫成"此物料為成品,需檢查銷售合同",用於代表現實中復雜的邏輯。

技術分享圖片

技術分享圖片

如圖6-13所示,創建原料物料類ZCL_MATERIAL_RAW,從抽象物料類繼承。

技術分享圖片

技術分享圖片

如圖6-14所示,自動繼承屬性MV_MATERIAL,為受保護可見度, 類型為物料號碼。MARA-MATNR。

技術分享圖片

技術分享圖片

如圖6-15所示,重定義繼承來的方法PRINT_INSP_DESC。

技術分享圖片

技術分享圖片

如圖6-16所示,該方法是對應的原料物料類的具體操作方法,比如獲取采購或生產數據,生成固定格式的報表,並發送到相應的輸出打印機等。我們寫成"此物料為原料,需檢查采購合同",用於代表現實中復雜的邏輯。

技術分享圖片

技術分享圖片

第三步,如圖6-17所示,創建表ZINSP_DESC_T:

列SORT_NUM代表序號。

列MATERIAL_TYPE存儲著SAP標準的物料類型。

列CLASS_TYPE存儲著處理相應物料類型的相應的物料類類名(類名需要大寫)。然後參照"數據字典"章節,維護列的Domain,數據類型和維護表等工作。

技術分享圖片

技術分享圖片

如圖6-18所示,運行SM30,將SAP標準的物料類型"ROH原料類型",及其對應的處理類"ZCL_MATERIAL_RAW",物料類型"FERT成品類型",極其對應的處理類"ZCL_MATERIAL_FIN"。添加到表中。

在Java和.NET中,大多使用XML文件來保存類似的服務註冊,SAP ABAP中最為方便的就是用數據庫表。

技術分享圖片

技術分享圖片

第四步,如圖6-19所示,創建簡單工廠類ZCL_MATL_SPL_FACTORY,這是第一層的調用類,模式控制的核心代碼定義在這一層 ,這個類將實現根據物料動態創建物料子類類型(也就是用於創建物料類對象的簡單類工廠),並實現多態的能力,多態在這個架構中將展現其威力。

類ZCL_MATL_SPL_FACTORY是普通的Public類型的非抽象類。

技術分享圖片

技術分享圖片

如圖6-20所示,設定方法GET_MATERIAL_OBJ,可見類型為Public,該方法是根據物料號碼,獲取物料類型,繼而獲得對應的物料類的名稱並創建類對象實例,方法可以是靜態類型方法(Static Method),即可以用類名來訪問方法(用=>符調用)。

技術分享圖片

技術分享圖片

如圖6-21所示,設定方法的輸入參數 IV_MATERIAL_ID,是傳入的物料號碼MARA-MATNR。

設定方法的返回參數 RO_MATERIAL,類型是抽象類物料對象類型ZCL_MATERIAL。方法將其實例化後作為返回值傳出,實例化的對象都是物料類的可實例化的子類對象,然後賦值給父類物料類對象進行上轉型,此處就是典型的多態的應用。

技術分享圖片

技術分享圖片

代碼根據傳入的物料號碼,在標準表MARA中查詢出物料類型,然後根據物料類型去自定義表格中查詢對應的處理類,然後創建對應類對象實例作為返回的參數,代碼如示例程序6.2所示,代碼中的"動態創建類對象 ro_material,類型為註冊表中的類的類型"即是按子類類型創建父類對象,即向上轉型的多態的實現。

"示例程序6.2

METHOD get_material_obj.

DATA: lv_material_type TYPE mara-mtart,
lv_material TYPE mara-matnr,
lv_class TYPE char30.

DATA:
exc_ref TYPE REF TO cx_root,
exc_text TYPE string,
lv_type_name TYPE string,
lv_method_name TYPE string.

"先根據物料號碼查詢物料類型
SELECT SINGLE mtart FROM mara INTO lv_material_type
WHERE matnr = iv_material_id.
IF sy-subrc = 0.
"在根據物料類型查詢註冊表中對應的物料類的類型
SELECT SINGLE class_type FROM zinsp_desc_t INTO lv_class
WHERE material_type = lv_material_type.
ENDIF.
"如果有查詢記錄則開始動態創建類
IF sy-subrc = 0.
lv_type_name = lv_class. "類名必須大寫
TRANSLATE lv_type_name TO UPPER CASE.
TRY.
"動態創建類對象 ro_material,類型為註冊表中的類的類型,
CREATE OBJECT ro_material TYPE (lv_type_name).
CATCH cx_sy_create_object_error INTO exc_ref.
exc_text = exc_ref->get_text( ).
MESSAGE exc_text TYPE ‘I‘.
ENDTRY.
ENDIF.

ENDMETHOD.

第五步,創建最終的調用程序,對於工廠類的方法GET_MATERIAL_OBJ,因為該方法為靜態方法,可以不創建類對象直接通過類名稱調用,調用後可以取得子類的對象實例。

然後再調用類的方法PRINT_INSP_DESC,根據多態,自動根據物料類型,實現子類具體的業務處理。

代碼如下:

"示例程序6.3

REPORT zrep_cls_022.

DATA:
lv_exref TYPE REF TO cx_root,
lv_msgtxt TYPE string.
DATA go_material TYPE REF TO zcl_material.
"輸入物料號碼
PARAMETERS: p_matnr LIKE mara-matnr.
START-OF-SELECTION.
TRY.
"不用創建調用工廠類的實例,通過類名調用靜態方法
"GET_MATERIAL_OBJ,取得子類的對象實例
go_material = zcl_matl_spl_factory=>get_material_obj( p_matnr ).
IF go_material IS BOUND.
"調用類的方法PRINT_INSP_DESC ,實現子類具體的業務處理
go_material->print_insp_desc( ).
ELSE.
WRITE: / ‘對應物料類型未維護打印信息.‘.
ENDIF.
CATCH cx_root INTO lv_exref.
lv_msgtxt = lv_exref->get_text( ).
WRITE: / lv_msgtxt.
CLEANUP.
ENDTRY.

如圖6-22所示,運行程序,輸入物料號"FIN1001",其物料類型為"FERT

成品類型",代碼如示例程序6.3所示。

技術分享圖片

技術分享圖片

如圖6-23所示,執行結果就是子類"ZCL_MATERIAL_FIN"成品物料類的打印方法。

技術分享圖片

技術分享圖片

如圖6-24所示,運行程序,輸入物料號"RAW2010",物料類型為"ROH原料類型",運行程序。

技術分享圖片

技術分享圖片

如圖6-25所示,執行結果就是子類"ZCL_MATERIAL_RAW"原料物料類的打印方法。

技術分享圖片

技術分享圖片

如圖6-26所示,運行程序,輸入物料號"SEMI001",物料類型為"HALB半成品類型",運行程序。

技術分享圖片

技術分享圖片

如圖6-27所示,執行結果就是未能找到子類,打印"對應物料類型未維護打印信息."的信息。

技術分享圖片

技術分享圖片

物料類的代碼如示例程序6.4所示。

"示例程序6.4

為了節約篇幅,物料類的code based 代碼請參照Github代碼6.4

<https://github.com/ABAPOOP/ABAP_OOP_SAMPLE/blob/master/ABAP_OOP_Sample_6.04.txt >

看到上面的實現方法,大家可能會說"莫名其妙啊?例子中的代碼原來一共就一個程序,20多行的代碼,每次擴展我就復制黏貼,然後改一改就好了。

現在用了這些原則和模式,需要創建幾個類,又要創建表,並且全部代碼變成了200多行,而其中近100行都是和打印無關的模式和控制的代碼——這不是畫蛇添足,自找麻煩嗎?"

這是一個好問題,以下我們要講的所有原則和模式都是會引入一些"冗余的"模式和控制代碼,我們幹脆就在這一節裏闡述一下作者對為什麽采用這些原則和模式控制的理解。

為什麽要采用這些原則和模式呢?

1. 為了建立一個良好的系統管理架構

如果你開了一家有一定的規模公司,你一定會架構好你的企業管理架構,管理學中的管理架構有管理層級和管理寬度的概念,層級就是從最高層到最底層的層級,管理寬度就是每層能夠有效監督的下屬人數。越是高層,對智力和抽象能力的要求越高,管理的方式就越是關註方向性和抽象性的問題,而不是具體化的業務。最高層一般就是3到13人(想想大多數公司董事會的人數,基本也就這麽多),作為董事長的你,主要管理好這幾個高層就可以了。而越往下的管理層級,管理的下屬人數就越多,他們關註的問題也就越為具體和瑣碎。越高層的人員替換和業務流程修改的代價越高(比如一個公司替換CEO的代價),而越低層級的人員替換和業務流程修改的代價卻越低。

一旦建立起來扁平而有效的管理架構和寬度,公司的業務發展就有了骨架,在管理層的運作下,基層員工的業務是很容易拓展的。從企業的人員"收益率"的角度出發,管理人員的收益率要遠大於具體的業務人員。

這些和具體業務無關的模式控制代碼就像是公司的管理架構和管理人員,在業務簡單的時候,模式控制控制代碼有100行,占了50%的代碼量,管理層當然低效而冗余。

而現實中的業務從來都不是這麽簡單的,動輒以上千行計,這時,控制代碼所占程序的比率就不會超過10%了,管理效率就體現出來了。

而當代碼隨著業務迅速增長的時候,模式控制代碼就像公司的管理層人員,不會像底層人員迅速增長,這時候的模式控制代碼數量就在整個系統中的數量比重越來越小,但控制代碼起到的作用依然是決定性的,系統的可擴展性,可維護性在一開始創建管理架構的時候就被決定了。

我們創建的模式控制代碼(包括幾個類和數據表),就是搭建這個系統的管理架構,在程序很簡單的時候當然是小題大做,但處理現實中的復雜系統,搭建一個有前瞻性的架構,就是"畢先利其器"的必要過程.

2.獲得更高的軟件的"代碼收益率"

我們用一個新名詞,"代碼收益率"來解釋。像計算像投資收益率一樣計算產出收益和投入的資產的比率。如下列公式所示,如果代碼也需要計算收益率的話,我們計算一下模式與控制部分的代碼收益率如何,列一個簡單的公式:

技術分享圖片

這裏,"手工編寫的業務代碼行數"是隨著業務的擴展和改變而不斷增加的需要手工加入的新的邏輯(其他共有的邏輯則通過類的復制和繼承即可得到),而核心的"模式與控制代碼"則增長不會很大,在良好的設計原則和模式下,甚至能做到這部分的零增長。

從成本的角度來看,開發成本在最開始的時候有架構師來定義最初的模式與控制,這時的成本是最高的。但系統擴展時,開發人員只要按照固定的模式添加新的類和配置,照貓畫虎即可,由一般的開發人員進行擴展就夠了,其開發成本是逐漸降低的。

由此可見,模式和控制代碼是用於控制全局的,所有新增的代碼都能夠在它的控制之下,所以這種模式控制的代碼的"代碼收益率"是最高的。是值得你投入精力去學習和實現的。

3. 降低軟件的開發和維護成本

舉一個實際項目中的例子,作者參與一個超過6000行的中型的ABAP後臺程序設計和測試,這個程序由基於BAdI的增強觸發,負責多種業務類型下的數據處理,一開始,我們用的是ABAP的一般結構化編程。隨著業務類型的增加(每幾個月都會增加一種類型),我們每次都要在已有的程序中添加新的業務類型,即便采用了功能和模塊化設計,但修改的代碼量還是重復和復雜,每次都要美國的架構師親自參與代碼設計和指導,然後由印度和中國的ABAPer們開發實現。

測試就更加麻煩,每次的測試都要用一個Excel表格才能記錄下所有的回退功能測試(就是對以前的功能的測試,防止新加的功能影響以往的功能)。

還曾經因為一次代碼更新了一個公有的模塊,而回退測試沒有覆蓋全,造成了上線後的系統錯誤。

最後,我們采用了面向對象ABAP和設計原則(開放封閉原則)與模式(主要是增強的簡單工廠模式)重構了這個程序,創建了幾個控制類和控制數據表,將業務類型封裝到一個抽象類中,然後將每個具體的業務類型定義為這個抽象類的子類。控制類的代碼和數據表如果用代碼行數來核算的話只有200多行。

重構後,目前每次擴展業務時,只需要客戶定義好新業務的基本規則(這些規則間很類似,可以重用大部分代碼),確定最核心的代碼邏輯,然後交給一個一般的開發人員去做兩件事情:

先用SE24按照現有的子類為模板,復制出一個新的類型,修改其中的某些方法來實現新的規則(我們視這部分的實現類不是模式與控制代碼,而是具體的業務實現代碼)。

然後再到數據配置表SM30中添加上這種業務類型就可以了。即便是一般的開發人員,這個工作既不復雜也無風險。

而原來冗長的BAdI的主程序,目前只有100多行,並且自重構後,我們添加過多種業務類型,但這些模式控制代碼和以前的業務類代碼從來不用修改和增加過。

至於測試,就更高效了,重構後的代碼,在前幾次添加規則時我們還做回退測試,因為每次添加業務類型的都是創建一個新的類(對擴展開放),從來都不會去修改以前的類和代碼(對修改關閉),所以對以前的邏輯不會有任何影響,到後來我們只測試新加的業務功能,連繁瑣的回退測試都省略了。而且每次上線沒有因為這個新架構而產生任何問題。

架構師采用良好的架構設計後,對於後期的功能擴展來說,價格高的架構師基本再不用參與這類擴展工作,而價格低的開發人員也有章可循沒有開發風險,測試則更是可以自動化進行或者減少回退測試,進一步降低了成本。

表6-3對比了作者在實際工作中的參與的這一項代碼重構前後的效果和成本對比。

技術分享圖片

NO.

項目

原有面向過程代碼

重構後的面向對象代碼

1

手寫代碼行數

6000行,幾乎所有代碼都需要手工編寫。

僅主程序代碼行數就近2000行,閱讀和修改都比較困難。

3000行,(全部代碼超過了一萬行,但是大部分代碼都是系統生成的,或者采用復制類的方法自動生成的,並且代碼分散在類方法中,易於理解和閱讀。新加功能時,我們復制一個新的類,然後只需要根據業務需要,修改類中的幾個方法即可,而控制類的代碼基本沒有增長過。)

2

重新添加一個業務功能後,回退測試(Regression Test)所耗時間

30小時,每次添加一個新業務功能,都要修改現有代碼,必須進行全面的回退測試,保證新加功能後的代碼沒有影響以往的業務邏輯。

0小時,因為采用了增強的工廠模式,遵循了開放封閉原則,以前的業務功能代碼不用進行任何修改,以前的代碼連編譯都不需要,不再需要回退測試。

3

新功能測試所需時間

5小時

5小時,開放封閉原則允許新加功能,新功能測試和原來用時一致。

4

上線後發生的錯誤次數

10+次,因為每都需要對原有代碼進行頻繁調整,出錯概率很大。

1次,並且是新功能遷移時發生的問題,因為增新功能不會影響以往的業務邏輯

5

重新添加一個業務功能所需時間

80+小時,每次都需要架構師親自審閱和設計,指導開發代碼。

30+小時,僅需架構師設計和審閱代碼即可。

為了驗證我的解釋,我們來測試一下,當業務上有一個新的類型"半成品物料"需要添加進來時,看該架構是否能做到只添加新代碼,不用修改原來的代碼。

如圖6-28,我們新加"半成品物料"後的系統結構如下所示,需新加一個子類B3,然後新加一條數據庫記錄即可,對虛線內的原有的系統代碼(也包括報表主程序ZREP_CLS_022)不用做任何修改,連重新編譯都不需要。

技術分享圖片

技術分享圖片

我們加入一個新的物料類"ZCL_MATERIAL_SEMI",代表物料類型 "半成品類型",專門處理SAP物料類型為"HALB"的半成品物料的打印。

如圖6-29所示,首先進入SE24,根據現有的類ZCL_MATERIAL_RAW,點擊復制按鈕,復制一個近似的半成品類ZCL_MATERIAL_SEMI。

技術分享圖片

技術分享圖片

如圖6-30所示,復制一個半成品類ZCL_MATERIAL_SEMI。

技術分享圖片

技術分享圖片

如圖6-31所示,半成品類ZCL_MATERIAL_SEMI同樣是繼承自類ZCL_MATERIAL,僅需要修改對應的Description等信息。

技術分享圖片

技術分享圖片

如圖6-32所示,為半成品類ZCL_MATERIAL_SEMI重新編寫那些需要修改的方法的代碼邏輯,不用修改的代碼的方法則繼續沿用以前的邏輯,不用處理。

技術分享圖片

技術分享圖片

如圖6-33所示,設定半成品物料的打印信息,然後激活這個半成品類。

技術分享圖片

技術分享圖片

如圖6-34所示,添加完新的類後,第二步就是進入SM30,為類註冊表ZINSP_DESC_T,新添加記錄,SAP標準物料類型為HALB(半成品),對應的類型處理類ZCL_MATERIAL_SEMI。

技術分享圖片

技術分享圖片

如圖6-35所示,前兩步的添加代碼和添加記錄完成後,我們不用修改,也不用編譯任何以前的類和主程序代碼,直接運行程序ZREP_CLS_022,然後輸入物料類型SEMI001,物料其對應的SAP標準物料類型為HALB(半成品)。

技術分享圖片

技術分享圖片

如圖6-36所示,代碼可以根據物料類型,找到相應的處理類,觸發相應的半成品物料類的方法來處理新的業務邏輯,而且,程序原來的針對原料和成品的處理邏輯不受任何影響。可見,該架構符合對擴展開放,對修改關閉的開放封閉原則,擁有較為穩定和易於擴展的系統結構。

技術分享圖片

技術分享圖片

該架構的核心就是利用了多態的特性,將"物料"抽象為較為穩定的,很少修改的抽象的父類;而具體的物料(成品,半成品,原料)則代表了具體多變的可以隨時添加和修改的具體的物料類型。

采用繼承讓各個物料子類有不同的處理方式。

采用多態根據當前的物料類型創建對應的處理類對象進行處理。

該系統邏輯依然是根據不同的物料類型來處理物料的不同檢驗方式,但把原來固定的IF / ELSE邏輯改成了工廠類中動態的表記錄的讀取的方式,獲得相應物料類型的處理類的名稱,並動態創建上轉型多態的父類對象。從而完全符合了開放封閉原則。該"增強的簡單工廠"架構是一種很實用並符合很多業務場景(不僅僅SAP業務開發會遇到的場景)的設計方式。

以上的開放封閉原則的示例即能幫助我們來實現一種即插即用的組件式的較為穩定和易於擴展的軟件系統架構。

《SAP ABAP面向對象程序設計:原則、模式及實踐》

技術分享圖片

https://book.douban.com/subject/30317853/

http://www.duokan.com/shop/tbt/book/179473

https://item.jd.com/12423999.html

https://e.jd.com/30429611.html

6.3 SAP ABAP 開放封閉原則(OCP)- 摘自 《SAP ABAP面向對象程序設計:原則、模式及實踐》