组合模式
组合模式定义:将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式设计到的角色:
1.Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
2.Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。
3.Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。
我们经常遇到的文件系统,或者公司部门结构,产品分类等,就非常适合用组合模式来处理,下面就公司结构做个demo。先看类图
demo如下
package com.example.demo; public interface Element { String getName(); void delete(); void addElement(String name ); void deleteElement(String name); Element getElement(int index); }
package com.example.demo; import java.util.ArrayList; import java.util.List; public class Department implements Element{ private String name; private Element superior; private List<Element> child; public Department() { } public Department(String name, Element superior) { this.name = name; this.superior = superior; this.child = new ArrayList<>(); } @Override public String getName() { return name; } @Override public void delete() { List<Element> copy = new ArrayList<Element>(child); for (Element e:copy){ e.delete(); } if(superior != null){ superior.deleteElement(name); } } @Override public void deleteElement(String name){ for (Element e:child){ if(e.getName().equals(name)){ child.remove(e); break; } } } @Override public Element getElement(int index) { return child.get(index); } @Override public void addElement(String name ) { //名字中含有de的说明是一个部门 if (name.contains("de") ){ child.add(new Department(name,this)); }else{ child.add(new Member(name,this)); } } }
package com.example.demo; public class Member implements Element{ private String name; private Element superior; public Member(String name, Element superior) { this.name = name; this.superior = superior; } @Override public String getName() { return name; } @Override public void delete() { superior.deleteElement(name); } @Override public void addElement(String name) { } @Override public void deleteElement(String name) { } @Override public Element getElement(int index) { return null; } }
package com.example.demo; public class Client { public static void main(String[] args) { Element total = new Department("总公司",null); total.addElement("总经理"); total.addElement("deFinance"); total.addElement("deSales"); Element finance = total.getElement(1); Element sales = total.getElement(2); finance.addElement("财务经理"); finance.addElement("财务职员张三"); sales.addElement("销售经理"); display(null,total); System.out.println(); total.getElement(0).delete(); sales.delete(); finance.getElement(1).delete(); display(null,total); System.out.println(); total.delete(); display(null,total); } public static void display(String prefix,Element e){ if(prefix ==null){ prefix=""; } System.out.println(prefix + e.getName()); if(e instanceof Department){ for(int i=0;;i++){ try { if(e.getElement(i)!= null){ display(prefix+"--",e.getElement(i)); } } catch (Exception e1) { break; } } } } }
执行client中main方法,结果如下:
可以看出,通过适用组合模式,我们对公司下员工和部门的操作是一致的。组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以像处理简单元素一样来处理复杂元素,如果你想要创建层次结构,并可以在其中以相同的方式对待所有元素,那么组合模式就是最理想的选择。
组合模式的适用场景:
1.表示对象的部分-整体层次结构。
2.用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。