一、什么是组合模式
组合(Composite Pattern)模式的定义:有时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性。
组合模式包含以下主要角色包含以下主要角色:
- 树叶抽象构件(Component)角色:它的主要作用是为树叶构件声明公共接口,并实现它们的默认行为。
- 树枝抽象构件(BranchComponent)角色:它的主要作用是为树枝构件声明公共接口,并实现它们的默认行为,扩展了树叶抽象角色。
- 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
- 树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
二、享元模式的实现
组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点。
- 树叶抽象构件(Component)
/**
* @author FluffyCatkin
* @version 1.0
* @date 2020/1/6 0006 15:56
* @description 抽象构件(Component)角色:它的主要作用是为树叶构件声明公共接口,并实现它们的默认行为。
*/
@FunctionalInterface
public interface Component {
void operation();
}
- 树叶构件(Leaf)
/**
* @author FluffyCatkin
* @version 1.0
* @date 2020/1/6 0006 16:01
* @description 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
*/
public class Leaf implements Component {
private String leafName;
public Leaf(String leafName) {
this.leafName = leafName;
}
@Override
public void operation() {
System.out.println("叶子节点:"+leafName+"被调用!");
}
}
- 树枝抽象构件(BranchComponent)
/**
* @author FluffyCatkin
* @version 1.0
* @date 2020/1/6 0006 15:56
* @description 树枝抽象构件(BranchComponent)角色:它的主要作用是为树枝构件声明公共接口,并实现它们的默认行为,扩展了树叶抽象角色。
*/
public interface BranchComponent extends Component{
/**
* 新增叶子
* @param component 叶子
*/
void add(Component component);
/**
* 移除叶子
* @param component 叶子
*/
void remove(Component component);
/**
* 查找叶子
* @param index 叶子下标
* @return 叶子
*/
Component getChild(int index);
}
- 树枝构件(Composite)
/**
* @author FluffyCatkin
* @version 1.0
* @date 2020/1/6 0006 16:01
* @description 树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法
*/
public class Composite implements BranchComponent {
private List<Component> children = new ArrayList<>();
private String compositeName ;
public Composite(String compositeName) {
this.compositeName = compositeName;
}
@Override
public void operation() {
System.out.println("树枝:"+compositeName+"被调用!");
children.parallelStream().forEach(Component::operation);
}
/**
* 新增叶子
* @param component 叶子
*/
@Override
public void add(Component component){
children.add(component);
}
/**
* 移除叶子
* @param component 叶子
*/
@Override
public void remove(Component component){
children.remove(component);
}
/**
* 查找叶子
* @param index 叶子下标
* @return 叶子
*/
@Override
public Component getChild(int index){
return children.get(index);
}
}
- 测试类
/**
* @author FluffyCatkin
* @version 1.0
* @date 2020/1/6 0006 15:53
* @description 组合模式
*
* 在现实生活中,存在很多“部分-整体”的关系,例如,大学中的部门与学院、总公司中的部门与分公司、学习用品中的书与书包、生活用品中的衣月艮与衣柜以及厨房中的锅碗瓢盆等。在软件开发中也是这样,例如,文件系统中的文件与文件夹、窗体程序中的简单控件与容器控件等。对这些简单对象与复合对象的处理,如果用组合模式来实现会很方便。
* 组合模式的定义与特点:
* 组合(Composite)模式的定义:有时又叫作部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。
* 组合模式的主要优点有:组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
* 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
*
* 其主要缺点是:设计较复杂,客户端需要花更多时间理清类之间的层次关系;
* 不容易限制容器中的构件;
* 不容易用继承的方法来增加构件的新功能;
* 模式的结构:
* 组合模式包含以下主要角色。
* 树叶抽象构件(Component)角色:它的主要作用是为树叶构件声明公共接口,并实现它们的默认行为。
* 树枝抽象构件(Component)角色:它的主要作用是为树枝构件声明公共接口,并实现它们的默认行为,扩展了树叶抽象角色。
* 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
* 树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
*
* 组合模式的应用场景:
* 前面分析了组合模式的结构与特点,下面分析它适用的以下应用场景。在需要表示一个对象整体与部分的层次结构的场合。
* 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
*
*/
public class Main {
/**
* 测试组合模式
*/
@Test
public void compositeTest(){
//组装树形结构
Composite composite1 = new Composite("树枝1");
Composite composite2 = new Composite("树枝2");
Leaf leaf1 = new Leaf("叶子1");
Leaf leaf2 = new Leaf("叶子2");
Leaf leaf3 = new Leaf("叶子3");
composite1.add(leaf1);
composite1.add(composite2);
composite2.add(leaf2);
composite2.add(leaf3);
//遍历
composite1.operation();
}
}
执行结果:
树枝:树枝1被调用!
树枝:树枝2被调用!
叶子节点:叶子3被调用!
叶子节点:叶子2被调用!
叶子节点:叶子1被调用!
Process finished with exit code 0
三、应用场景
它适用的以下应用场景:
- 在需要表示一个对象整体与部分的层次结构的场合。
- 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
四、优缺点分析
组合模式的主要优点有:
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
其主要缺点是:
- 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
- 不容易限制容器中的构件;
- 不容易用继承的方法来增加构件的新功能;
代码地址:https://gitee.com/fluffycatkin/JavaDesignModel.git
原文出处:http://c.biancheng.net/view/1373.html