设计模式——组合模式

什么是组合模式(Composite)

组合模式属于结构型模式,它适用于对象层次为树形结构的类组合。

组合模式使得用户对单个对象和组合对象的访问和操作具有一致性,即组合模式中,客户能以一致性的方式去处理单个对象和组合对象。

UML图

UML

首先顶层应该是一个Component部分类,抽象类,接口,它是什么都行。我们现在假定它是一个接口,这个Component中定义了一些操作方法operation1,operation2等等。这些操作方法的定义其实是希望用户能够以一致性的方式去处理单个对象和组合对象,因为后面单个对象和组合对象都会实现或者继承这个Component。Component中还定义了add方法,接受的参数是Component意思就是在实现Component接口或者抽象类的类中会包含一个Component的容器(可能是list,set,map等等),对于这个容器的操作还有get或者remove方法也在这个Component接口中定义了。

我们可以肯定的是,组合对象需要实现Component中定义的对于装有Component的容器的增删获取等操作。而叶子节点因为底下不再包含Component类了,所以叶子节点只需要实现Component中定义的需要对单个对象和组合对象进行一致性处理的操作方法。

组合模式代码示例

首先我们有一个学校,学校里面有许多学院,学院下面又有很多专业。

我们现在需要打印出整个学校下面所有的学院和专业,我们就可以使用组合模式。

组合模式特别适用于一些树形的类结构

Component

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
public abstract class OrganizationComponent {

private String name;

private String description;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}


public OrganizationComponent(String name, String description) {
this.name = name;
this.description = description;
}

public void add(OrganizationComponent organizationComponent) {
throw new UnsupportedOperationException();
}

public void remove(OrganizationComponent organizationComponent) {
throw new UnsupportedOperationException();
}

public abstract void print();

}

组合对象Composite(这里是University和College)

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
public class College extends OrganizationComponent {

List<OrganizationComponent> organizationComponentList = new ArrayList<>();

public College(String name, String description) {
super(name, description);
}

@Override
public String getName() {
return super.getName();
}

@Override
public void setName(String name) {
super.setName(name);
}

@Override
public String getDescription() {
return super.getDescription();
}

@Override
public void setDescription(String description) {
super.setDescription(description);
}

@Override
public void add(OrganizationComponent organizationComponent) {
organizationComponentList.add(organizationComponent);
}

@Override
public void remove(OrganizationComponent organizationComponent) {
organizationComponentList.remove(organizationComponent);
}

@Override
public void print() {
System.out.println("------" + this.getName() + "-------");
for (OrganizationComponent organizationComponent: organizationComponentList) {
organizationComponent.print();
}
}
}

public class University extends OrganizationComponent {


public University(String name, String description) {
super(name, description);
}

List<OrganizationComponent> organizationComponentList = new ArrayList<>();

@Override
public String getName() {
return super.getName();
}

@Override
public void setName(String name) {
super.setName(name);
}

@Override
public String getDescription() {
return super.getDescription();
}

@Override
public void setDescription(String description) {
super.setDescription(description);
}

@Override
public void add(OrganizationComponent organizationComponent) {
organizationComponentList.add(organizationComponent);
}

@Override
public void remove(OrganizationComponent organizationComponent) {
organizationComponentList.remove(organizationComponent);
}

@Override
public void print() {
System.out.println("---------" + this.getName() + "-----------");
for (OrganizationComponent organizationComponent :organizationComponentList) {
organizationComponent.print();
}
}
}

单个对象(叶子节点这里是Department)

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
public class Department extends OrganizationComponent{

@Override
public String getName() {
return super.getName();
}

@Override
public void setName(String name) {
super.setName(name);
}

@Override
public String getDescription() {
return super.getDescription();
}

@Override
public void setDescription(String description) {
super.setDescription(description);
}

public Department(String name, String description) {
super(name, description);
}


@Override
public void print() {
System.out.println("------" + this.getName() + "----");
}
}

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Client {

public static void main(String[] args) {
OrganizationComponent university = new University("江苏大学", "重点一本");

OrganizationComponent computerCollege = new College("计算机学院", "计算机学院");
OrganizationComponent infoCollege = new College("信息工程学院", "信息工程学院");

computerCollege.add(new Department("软件工程", "11"));
computerCollege.add(new Department("物联网工程", "22"));
computerCollege.add(new Department("计算机", "33"));

infoCollege.add(new Department("通信工程", "44"));

university.add(computerCollege);
university.add(infoCollege);

university.print();

}

}

实际运用

Tomcat的运用

在Tomcat中,四大容器Engine,Host,Context,Warpper都继承了Container接口,在Container接口中定义了对容器的增删等操作。

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
public interface Container extends Lifecycle {

public static final String ADD_CHILD_EVENT = "addChild";
public static final String ADD_VALVE_EVENT = "addValve";
public static final String REMOVE_CHILD_EVENT = "removeChild";
public static final String REMOVE_VALVE_EVENT = "removeValve";

public Log getLogger();

public String getLogName();

public ObjectName getObjectName();

public String getDomain();

public String getMBeanKeyProperties();

public Pipeline getPipeline();

public Cluster getCluster();

public void setCluster(Cluster cluster);

public int getBackgroundProcessorDelay();

public void setBackgroundProcessorDelay(int delay);

public String getName();

public void setName(String name);

public Container getParent();

public void setParent(Container container);

public ClassLoader getParentClassLoader();

public void setParentClassLoader(ClassLoader parent);

public Realm getRealm();

public void setRealm(Realm realm);

public void backgroundProcess();

public void addChild(Container child);

public void addContainerListener(ContainerListener listener);

public void addPropertyChangeListener(PropertyChangeListener listener);

public Container findChild(String name);

public Container[] findChildren();

public ContainerListener[] findContainerListeners();

public void removeChild(Container child);

public void removeContainerListener(ContainerListener listener);

public void removePropertyChangeListener(PropertyChangeListener listener);

public void fireContainerEvent(String type, Object data);

public void logAccess(Request request, Response response, long time,
boolean useDefault);

public AccessLog getAccessLog();

public int getStartStopThreads();

public void setStartStopThreads(int startStopThreads);

public File getCatalinaBase();

public File getCatalinaHome();
}

tomcat

上图是继承实现Container的类结构

-------------本文结束感谢阅读-------------