组合模式
组合模式
简介
组合模式(Composite Pattern)有时候又叫做部分-整体模式,将对象组合成树形结构以表示“部分整体”的层次结构。它使我们在树型结构的问题中,模糊了简单元素和复杂元素的概念。
树形结构:
客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。组合模式让你可以优化处理递归或分级数据结构。有许多关于分级数据结构的例子,使得组合模式非常有用武之地。关于分级数据结构的一个普遍性的例子是你每次使用电脑时所遇到的:文件系统。文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。
涉及角色
- Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component
- Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。
- Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。
组合模式应用场景
以下情况下适用Composite模式:
1.你想表示对象的部分-整体层次结构
2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
组合模式UML图
组合模式代码实例
业务场景
部门和员工
-
部门属性:name,description,List(用于存放员工和其他部门)
-
员工属性:name,sal(月薪)
-
部门可以添加子部门和员工。
-
使用组合模式完成以上业务逻辑。
代码
Component包括叶子节点中共有的属性,和叶子节点中的方法,叶子节点中对同一个方法有不同的实现则用抽象方法,没有不同的实现则定义为普通方法,并抛出异常,叶子节点继承父类的时候重写这些普通方法。
// 部门和员工的父类,同一接口
abstract class Component {
private String name;
public Component(String name) {
this.name = name;
}
// 部门的方法
public void add(Component component) {
throw new UnsupportedOperationException();
}
public void remove(Component component) {
throw new UnsupportedOperationException();
}
public void get(int i) {
throw new UnsupportedOperationException();
}
public String getDescription() {
throw new UnsupportedOperationException();
}
// 员工的方法
public double getSal() {
throw new UnsupportedOperationException();
}
// 部门和员工共有的方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
abstract public void print(String preFix);
}
Leaf 包含Leaf 本身独有的属性和方法,并在继承父类后,重写那些自己可以使用的方法
// 部门
class Department extends Component {
private String description;
private List<Component> list = new ArrayList<>();
public Department(String name, String description) {
super(name);
this.description = description;
}
@Override
public void add(Component component) {
list.add(component);
}
@Override
public void remove(Component component) {
list.remove(component);
}
@Override
public void get(int i) {
list.get(i);
}
@Override
public String getDescription() {
return description;
}
@Override
public void print(String preFix) {
System.out.println(preFix + getName() + " : " + description);
Iterator<Component> it = list.iterator();
while (it.hasNext()) {
Component component = it.next();
component.print(preFix + "\t");
}
}
}
// 员工
class Emp extends Component {
private double sal;
public Emp(String name, double sal) {
super(name);
this.sal = sal;
}
@Override
public double getSal() {
return sal;
}
@Override
public void print(String preFix) {
System.out.println(preFix + "\t" + getName() + " : " + sal);
}
}
测试
public class ComponentPatter {
public static void main(String[] args) {
Component department1 = new Department("开发部", "软件工程师");
Component department2 = new Department("财务部", "会计");
Component department3 = new Department("人力部", "HR");
Component emp1 = new Emp("张三", 4000);
Component emp2 = new Emp("李四", 2000);
Component emp3 = new Emp("王五", 3000);
Component emp4 = new Emp("赵六", 5000);
Component emp5 = new Emp("田七", 6000);
department2.add(emp1);
department2.add(emp2);
department2.add(emp3);
department3.add(emp4);
department3.add(emp5);
department1.add(department2);
department1.add(department3);
department1.print(" ");
}
}
开发部 : 软件工程师
财务部 : 会计
张三 : 4000.0
李四 : 2000.0
王五 : 3000.0
人力部 : HR
赵六 : 5000.0
田七 : 6000.0