组合模式
Composite
定义: 将对象组合成树形结构来表示"部分–整体"的层次结构
组合模式使得单个对象和组合对象的使用具有一致性
角色
角色图(大话设计模式图)
Component
: 抽象类或接口 用来访问和管理它的子部件:Leaf
或Composite
Composite
:Component
的子部件,拥有子节点,要实现与子部件相关方法Leaf
:Component
的子部件,没有子节点 (所以不用实现与子部件相关方法)
公司例子
组合模式把多个对象组合成树型结构
公司中有分公司或部门,公司或分公司就是Composite,因为它们一定有子节点,而部门就是Leaf,部门下面没有管理的部件了,所以部门是叶子节点
Composite: 公司,子公司
Leaf: 部门
例子代码
-
透明方式: Leaf也实现Component中与子部件相关方法,但这么做无意义
-
安全方式: 代码中Leaf未重写的使用了Component中的add,remove(抛出异常)
这么写当Leaf调用add,remove时会抛出异常,安全
代码结构图
Component
/**
* @author Tc.l
* @Date 2021/1/29
* @Description:公司接口
*/
public abstract class Component {
private String name;
protected String getName() {
return name;
}
public Component(String name) {
this.name = name;
}
protected void setName(String name) {
this.name = name;
}
public void add(Component component){
throw new UnsupportedOperationException();
}
public void remove(Component component){
throw new UnsupportedOperationException();
}
public abstract void printName();
}
Composite
/**
* @author Tc.l
* @Date 2021/1/29
* @Description:CompositeA(总公司)
*/
public class CompositeA extends Component{
//列表中装的是分公司或部门
private List<Component> components;
public CompositeA(String name) {
super(name);
components = new ArrayList<Component>();
}
@Override
public void add(Component component) {
components.add(component);
}
@Override
public void remove(Component component) {
components.remove(component);
}
@Override
public void printName() {
System.out.println(getName());
System.out.println("=======================");
for (Component component : components) {
component.printName();
}
System.out.println("=======================");
}
}
/**
* @author Tc.l
* @Date 2021/1/29
* @Description:CompositeB(分公司)
*/
public class CompositeB extends Component{
//列表中装的是部门
private List<Component> components;
public CompositeB(String name) {
super(name);
components = new ArrayList<Component>();
}
@Override
public void add(Component component) {
components.add(component);
}
@Override
public void remove(Component component) {
components.remove(component);
}
@Override
public void printName() {
System.out.println(getName());
System.out.println("-----------------------------");
for (Component component : components) {
component.printName();
}
System.out.println("-----------------------------");
}
}
Leaf
/**
* @author Tc.l
* @Date 2021/1/29
* @Description:Leaf(部门)
*/
public class Leaf extends Component{
public Leaf(String name) {
super(name);
}
@Override
public void printName() {
System.out.println(getName());
}
}
Client
public class Client {
public static void main(String[] args) {
//总公司
CompositeA head = new CompositeA("太菜了中国总公司");
//分公司
CompositeB jiangxiBranch = new CompositeB("太菜了江西分公司");
CompositeB guangdongBranch = new CompositeB("太菜了广东分公司");
//部门
Leaf finance = new Leaf("财务部");
Leaf technology = new Leaf("技术部");
head.add(jiangxiBranch);
head.add(guangdongBranch);
head.add(finance);
head.add(technology);
jiangxiBranch.add(finance);
guangdongBranch.add(technology);
head.printName();
}
}
/*
太菜了中国总公司
=======================
太菜了江西分公司
-----------------------------
财务部
-----------------------------
太菜了广东分公司
-----------------------------
技术部
-----------------------------
财务部
技术部
=======================
*/
排版不太好看还是画图出来明显
JDK中的组合模式
常用的HashMap就使用了组合模式
只不过它的Component抽象层有2层,一层接口一层抽象类
HashMap(Composite)聚合了子部件Node(Leaf) Node是HashMap的静态内部类
而在Component中抽象的put,remove方法,在HashMap(Composite)中进行重写,而在Node(Leaf)中未实现
因为Node是Leaf,没有子部件,实现put,remove无意义
Node实现Entry接口,Entry接口是Map的内部接口
static class Node<K,V> implements Map.Entry<K,V>
AbstractMap中的put方法也是安全方式
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
总结
特点
组合模式中定义了单个对象和组合对象这样的层次结构
单个对象:Leaf角色, 无子部件 (部门)
组合对象:composite角色 (分公司->部门) 还可以组合递归下去(总公司->分公司->部门)
一致性: 使用组合模式时不用关心到底是处理单个对象还是处理组合对象
使用场景
- 处理递归,分层的结构系统
- 需要体现 部分–整体结构
- 可以忽略单个对象和组合对象不同,统一使用组合中的对象时