目录
一、组合模式应用在哪些场景中
需求中是整体与部分的层次结构时,而且需求是树形结构,整体与部分用户希望忽略组合对象和单个对象的不同,统一使用组合结构的所有对象时,考虑用组合模式。
二、定义
将对象组合成树形结构以表示部分-整体的层次结构。组合模式使的用户对单个对象和组合对象的使用具有一致性。
三、UML图
四、实现方式
/**
* 组合整体抽象
*/
public abstract class Component {
protected String name;
protected Integer dept;
public Component(String name,Integer dept){
this.name=name;
this.dept=dept;
}
public void add(Component component) throws Exception{
throw new Exception("add error");
}
public void remove(Component component) throws Exception{
throw new Exception("remove error");
}
public Component getChild(int i) throws Exception{
throw new Exception("getChild error");
}
public List<Component> getChildren(){
return null;
}
public abstract void operation();
}
/**
* 部分对象叶子
*/
public class Leaf extends Component {
public Leaf(String name,Integer dept){
super(name,dept);
}
@Override
public void operation(){
String str="";
for(Integer i=0;i<dept;i++){
str+="*";
}
System.out.println(str+"叶子节点"+name);
}
}
/**
* 组合对象
*/
public class Composite extends Component {
private List<Component> components=new ArrayList<>();
public Composite(String name,Integer dept){
super(name,dept);
}
public void add(Component component) throws Exception{
components.add(component);
}
public void remove(Component component) throws Exception{
components.remove(component);
}
public Component getChild(int i) throws Exception{
return components.get(i);
}
public List<Component> getChildren(){
return components;
}
@Override
public void operation(){
String str="";
for(Integer i=0;i<dept;i++){
str+="*";
}
System.out.println(str+"组合节点"+name);
for(Component component:components){
component.operation();
}
}
}
客户端调用:
public class MinJson {
public static void main(String[] args) throws IOException {
try{
Composite composite=new Composite("文件夹1",0);
Composite composite2=new Composite("文件夹2",1);
Leaf leaf1=new Leaf("文件1",1);
Leaf leaf2=new Leaf("文件2",2);
Leaf leaf3=new Leaf("文件3",2);
composite2.add(leaf2);
composite2.add(leaf3);
composite.add(composite2);
composite.add(leaf1);
Composite composite3=new Composite("文件夹3",2);
Leaf leaf4=new Leaf("文件4",3);
Leaf leaf5=new Leaf("文件5",3);
composite3.add(leaf4);
composite3.add(leaf5);
composite2.add(composite3);
composite.operation();
}catch(Exception e){
}
}
}
实验结果:
组合节点文件夹1
*组合节点文件夹2
**叶子节点文件2
**叶子节点文件3
**组合节点文件夹3
***叶子节点文件4
***叶子节点文件5
*叶子节点文件1
Process finished with exit code 0
如上可以通过*号的个数,看出文件夹及文件的层级关系。
五、组合模式的优缺点
优点:组合模式让整体和部分用统一的组合组件去处理,使组合与单个透明化为统一的组合,并且组合中调用组合实现树状的递归调用,这样避免的判断分支,实现统一化处理。
缺点:用组合模式会让单个对象的某些操作隐藏,成为默认操作,这样不安全,如果安全性侧重的话,可以让单个对象和组合对象继承不同的抽象类或实现不同的接口,用安全性同样增加了分支判断。用组合模式的透明性在递归的环节组合对象操作也包括单个对象操作,这样在单一职责的原则上也有损耗,模式看具体的设计场景,择优选择。
六、组合模式的实际应用场景例子
文件系统的文件夹和文件、公司的部门及分公司、系统UI界面导航的主菜单-子菜单、前端设计页面-页面button等控件元素等等。