版权声明:本文为 冬夏 原创文章,可以随意转载,但请注明出处。
组合模式(Composite)允许你将对象组合成树形结构来表现“整体/部分”层次结构。
说到组合模式,Android 开发者们第一反应都会想到 View/ViewGroup。没错,View/ViewGroup 正是通过组合模式使用户能够以树状的形式访问它们。那么组合模式究竟是如何实现的呢?首先看一下组合模式的 UML 图。
假设我们现在有这么一个需求:需要按部门和等级建立公司的人员结构图,由于公司的组织结构和人员变动随时都有可能发生,所以,所以不能采用一个固定的数据结构。这种情况下使用组合模式是一个很好的选择。
我们尝试从组合模式的UML中找找编程的灵感。我们可以发现组合模式存在着一下几个特点:
- 叶子类和非叶子类都继承自同一个组合类
- 叶子类和非叶子类有针对性地继承组合父类的某些方法。
接着尝试用组合模式解决我们的需求。假设将所有员工分为两类,领导和员工,领导有雇佣和开除员工的权限,而员工有执行具体任务的业务能力。首先新建公共父类,拥有员工和领导的所有方法。
public class Component {
protected String name;
List<Component> subordinate;
public Component(String name){
this.name = name;
subordinate = new ArrayList<>();
}
public void add(Component c)//增加成员
{
throw new UnsupportedOperationException("该员工不支持此操作");
}
public void remove(Component c){ //删除成员
throw new UnsupportedOperationException("该员工不支持此操作");
}
public Component getChild(int i){ //获取成员
throw new UnsupportedOperationException("该员工不支持此操作");
}
public void operation(){ //业务方法
throw new UnsupportedOperationException("该员工不支持此操作");
}
public List<Component> getSubordinate() {
return subordinate;
}
@Override
public String toString() {
return name;
}
public void printAll(){
System.out.println(this);
for (Component employee : this.getSubordinate()) {
employee.printAll();
}
}
}
接着建立领导类和职员类
public class Employer extends Component {
public Employer(String name){
super(name);
}
public void add(Component c)//增加成员
{
subordinate.add(c);
}
public void remove(Component c){ //删除成员
subordinate.remove(c);
}
public Component getChild(int i){ //获取成员
return subordinate.get(i);
}
}
public class Employee extends Component {
public Employee(String name){
super(name);
}
@Override
public void operation() {
System.out.println("员工执行业务操作");
}
}
最后我们就可以简单地实现访问所有的员工了
public class Main {
public static void main(String[] agrs){
Employer CEO = new Employer("John");
Employer headSales = new Employer("Robert");
Employer headMarketing = new Employer("Michel");
Employee clerk1 = new Employee("Laura");
Employee clerk2 = new Employee("Bob");
Employee salesExecutive1 = new Employee("Richard");
Employee salesExecutive2 = new Employee("Rob");
CEO.add(headSales);
CEO.add(headMarketing);
headSales.add(salesExecutive1);
headSales.add(salesExecutive2);
headMarketing.add(clerk1);
headMarketing.add(clerk2);
//打印该组织的所有员工
CEO.printAll();
}
}
最后说一下组合模式的优缺点:
优点:
- 高层模块调用简单,由于不管是树枝还是叶子,对于高层来说都是 Component,所以对调用者来说没有任何区别。
- 节点自由增减,从代码中可以看出,如果想要在某个节点下新增节点,只要找到父节点就好了,非常容易扩展,符合开闭原则,对以后的维护非常有利。
缺点:
- 设计复杂,客户端需要花更多时间理清类之间的层次关系。(这个是几乎所有设计模式所面临的问题)。
- 指向不明,由于对于调用者来说,并不清楚当前节点是树枝还是树叶。