Статьи

Структурные образцы дизайна: составной образец

Ранее мы проверили схему адаптера , варианты использования и схему моста . Шаблон, который мы рассмотрим в этом посте, является составным шаблоном.

Следуя составному шаблону, мы «объединяем» объекты в древовидные структуры, представляющие частично-целые иерархии, поэтому клиенты могут обрабатывать отдельные объекты и композиции единообразно.

При упоминании иерархий слов первое, что приходит на ум, — это организации. Военная организация является отличным примером для сложной модели.

Одним из самых основных действий военнослужащих является выполнение заказов.
Таким образом, мы сделаем интерфейс, который определяет возможность выполнения заказов.

1
2
3
4
5
6
7
package com.gkatzioura.design.structural.composite;
 
public interface MilitaryPersonnel {
 
    void executeOrder();
 
}

Рядовой является самым низким званием в военной организации. Частное лицо не может делегировать задачу или отдавать приказы. Поэтому он просто выполнит заказ.

01
02
03
04
05
06
07
08
09
10
package com.gkatzioura.design.structural.composite;
 
public class Private implements MilitaryPersonnel {
 
    @Override
    public void executeOrder() {
 
    }
 
}

Выше рядового есть и другие звания, такие как майор, лейтенант, полковник и т. Д. Это офицерские звания, а офицеры выполняют приказы, но они также могут назначать приказы.

Так что интерфейс Officer будет указывать возможность назначать заказы.

1
2
3
4
5
6
7
package com.gkatzioura.design.structural.composite;
 
public interface Officer {
 
    void assignOrder();
 
}

Имейте в виду, что офицер, чтобы выполнить приказ, он предпримет некоторые действия самостоятельно, и он мог бы также назначить некоторые приказы персоналу более низкого ранга.

Таким образом, лейтенант сможет выполнять приказы, а также назначать приказы на звания ниже его.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.gkatzioura.design.structural.composite;
 
import java.util.ArrayList;
import java.util.List;
 
public class Lieutenant implements MilitaryPersonnel, Officer {
 
    private List<MilitaryPersonnel> lowerRankersonel = new ArrayList<>();
 
    public Lieutenant(List<MilitaryPersonnel> lowerRankersonel) {
        this.lowerRankersonel = lowerRankersonel;
    }
 
    public void addPrivateUnderCommand(Private soldier) {
        lowerRankersonel.add(soldier);
    }
     
    @Override
    public void executeOrder() {
         
        //other actions
 
        assignOrder();
 
        //other actions.
    }
 
    @Override
    public void assignOrder() {
 
        lowerRankersonel.forEach(lr->lr.executeOrder());
    }
}

То же самое относится и к лейтенанту, относится к майору, который может выполнять приказы и назначать приказы более низким званиям.

01
02
03
04
05
06
07
08
09
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
package com.gkatzioura.design.structural.composite;
 
import java.util.ArrayList;
import java.util.List;
 
public class Colonel implements MilitaryPersonnel, Officer {
 
    private List<MilitaryPersonnel> lowerRankersonel = new ArrayList<>();
 
    public Colonel(List<MilitaryPersonnel> lowerRankersonel) {
        this.lowerRankersonel = lowerRankersonel;
    }
 
    public void addPrivateUnderCommand(Private soldier) {
        lowerRankersonel.add(soldier);
    }
 
    public void addLieutenantUnderCommand(Lieutenant lieutenant) {
        lowerRankersonel.add(lieutenant);
    }
 
    @Override
    public void executeOrder() {
        //other actions
 
        assignOrder();
 
        //other actions
    }
 
    @Override
    public void assignOrder() {
        lowerRankersonel.forEach(lr->lr.executeOrder());
    }
}

В нашем сценарии общее является наивысшим рангом, и поэтому, когда он назначит ордер, этот ордер будет выполнен с помощью композита, который мы реализовали.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package com.gkatzioura.design.structural.composite;
 
import java.util.ArrayList;
import java.util.List;
 
public class General implements  Officer {
 
    private List<MilitaryPersonnel> lowerRankersonel = new ArrayList<>();
 
    public General(List<MilitaryPersonnel> lowerRankersonel) {
        this.lowerRankersonel = lowerRankersonel;
    }
 
    @Override
    public void assignOrder(MilitaryPersonnel militaryPersonnel) {
        militaryPersonnel.executeOrder();
    }
}

А основной класс будет отображать функциональность композита.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.gkatzioura.design.structural.composite;
 
import java.util.Collections;
 
public class CompositeScenario {
 
    public static void main(String[] args) {
 
        Private ryan = new Private();
        Lieutenant lieutenant = new Lieutenant(Collections.singletonList(ryan));
        Major major = new Major(Collections.singletonList(lieutenant));
        General general = new General();
        general.assignOrder(major);
    }
}

Как видно из общего объекта, клиент обрабатывает все объекты одинаково.

Вся иерархия представлена ​​в виде древовидной структуры.

Private — это лист Major, а лейтенант представляет Composite, который перенаправляет запросы в соответствующие дочерние компоненты.

Вы можете найти исходный код на github .

Опубликовано на Java Code Geeks с разрешения Эммануила Гкациоураса, партнера нашей программы JCG. См. Оригинальную статью здесь: Структурные Проектные Образцы: Составной Образец

Мнения, высказанные участниками Java Code Geeks, являются их собственными.