Метафора
Для примера можно рассмотреть управление солдатами в строю. Существует строевой устав, который определяет, как управлять строем и согласно этого устава абсолютно не важно кому отдается приказ (например, «шагом марш») одному солдату или целому взводу. Соответственно в устав (если его в чистом виде считать паттерном «компоновщик») нельзя включить команду, которую может исполнить только один солдат, но не может исполнить группа, или наоборот.
Назначение
Паттерн описывает интерфейс, позволяющий работать с группой объектов или отдельным объектом одинаково.
Примером может служить графический редактор, где Вам понадобилось одновременно закрасить несколько примитивов на экране. Для этого вы выделяете их и нажимаете кнопку закрасить, при выделении формируется композиционный объект, который содержит все примитивы. Команда закрасить поочередно выполняется для каждого. При этом редактор работает (посылает команду «закрасить») с одним абстрактным классом «Примитив», который поддерживает операцию закрашивания.
Данный паттерн является относительно низкоуровневым и лежит в основе других паттернов. Команды объединяются в составные команды, декоратор является составным объектом, посетители часто обходят составные объекты иерархической формы.
Диаграмма
- Component – базовый класс компонента, содержит операцию, а так же может содержать операции добавления, удаления и получения дочернего элемента.
- Composite – составной объект, который делегирует выполнение операции всем дочерним.
- Leaf – одиночный компонент, если операции с дочерними объектами лежат в базовом классе, он их не реализует, выдавая например исключение.
- Client – обработчик компонентов, который благодаря общему интерфейсу работает одинаково как с одиночными, так и с составными объектами.
Пример
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
*&---------------------------------------------------------------------* *& Определение классов шаблона *&---------------------------------------------------------------------* CLASS lcl_component DEFINITION ABSTRACT. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string, operation ABSTRACT, add ABSTRACT IMPORTING io_component TYPE REF TO lcl_component, remove ABSTRACT IMPORTING io_component TYPE REF TO lcl_component, get_child ABSTRACT IMPORTING iv_index TYPE i RETURNING VALUE(ro_component) TYPE REF TO lcl_component. PROTECTED SECTION. DATA: mv_name TYPE string. ENDCLASS. CLASS lcl_component IMPLEMENTATION. METHOD constructor. mv_name = iv_name. ENDMETHOD. ENDCLASS. CLASS lcl_leaf DEFINITION INHERITING FROM lcl_component. PUBLIC SECTION. METHODS: operation REDEFINITION, add REDEFINITION, remove REDEFINITION, get_child REDEFINITION. ENDCLASS. CLASS lcl_leaf IMPLEMENTATION. METHOD operation. WRITE: / mv_name. ENDMETHOD. METHOD add. ENDMETHOD. METHOD remove. ENDMETHOD. METHOD get_child. ENDMETHOD. ENDCLASS. CLASS lcl_composite DEFINITION INHERITING FROM lcl_component. PUBLIC SECTION. METHODS: operation REDEFINITION, add REDEFINITION, remove REDEFINITION, get_child REDEFINITION. PRIVATE SECTION. DATA: mt_childrens TYPE STANDARD TABLE OF REF TO lcl_component. ENDCLASS. CLASS lcl_composite IMPLEMENTATION. METHOD operation. WRITE: / mv_name. LOOP AT mt_childrens INTO DATA(lo_child). lo_child->operation( ). ENDLOOP. ENDMETHOD. METHOD add. APPEND io_component TO mt_childrens. ENDMETHOD. METHOD remove. DELETE mt_childrens WHERE table_line = io_component. ENDMETHOD. METHOD get_child. READ TABLE mt_childrens INDEX iv_index INTO ro_component. ENDMETHOD. ENDCLASS. *&---------------------------------------------------------------------* *& Работа с шаблоном *&---------------------------------------------------------------------* START-OF-SELECTION. DATA(lo_root) = NEW lcl_composite( iv_name = 'ROOT' ). DATA(lo_branch1) = NEW lcl_composite( iv_name = 'BR1' ). DATA(lo_branch2) = NEW lcl_composite( iv_name = 'BR2' ). DATA(lo_leaf1) = NEW lcl_leaf( iv_name = 'LF1' ). DATA(lo_leaf2) = NEW lcl_leaf( iv_name = 'LF2' ). lo_branch1->add( lo_leaf1 ). lo_branch1->add( lo_leaf2 ). lo_root->add( lo_branch1 ). lo_root->add( lo_branch2 ). lo_root->operation( ). |