暂时还没遇到需要这种设计模式的情景,笔者一般会把层次结构放到数据库里,用 parentId 来标识父子关系
1. 组合模式(Composite Pattern)
将对象组合成树形结构以表示 “部分-整体” 的层次结构,使得用户对单个对象和组合对象的使用具有一致性
组合模式的组成:
- 抽象根节点(Component):存放整体的默认行为和属性
- 树枝节点(Composite):存储叶子节点的集合
- 叶子节点(Leaf):存放真实对象
2. 流程
这里很像操作系统的文件结构
2.1 Component
代码语言:javascript复制public abstract class Component {
protected String name;
public Component(String name) {
this.name = name;
}
public abstract String hierarchical();
public abstract void addChild(Component component);
public abstract void removeChild(Component component);
public abstract Component getChild(int index);
}
2.2 Composite
代码语言:javascript复制public class Composite extends Component {
private List<Component> componentList;
public Composite(String name) {
super(name);
componentList = new ArrayList<>();
}
public String hierarchical() {
StringBuilder builder = new StringBuilder(this.name);
for (Component component : componentList) {
builder.append("n");
builder.append(component.hierarchical());
}
return builder.toString();
}
@Override
public void addChild(Component component) {
componentList.add(component);
}
@Override
public void removeChild(Component component) {
componentList.remove(component);
}
@Override
public Component getChild(int index) {
return componentList.get(index);
}
}
2.3 Leaf
代码语言:javascript复制public class Leaf extends Component {
public Leaf(String name) {
super(name);
}
@Override
public void printAll() {
System.out.println(this.name);
}
@Override
public void addChild(Component component) {
throw new UnsupportedOperationException();
}
@Override
public void removeChild(Component component) {
throw new UnsupportedOperationException();
}
@Override
public Component getChild(int index) {
throw new UnsupportedOperationException();
}
}
2.4 案例
代码语言:javascript复制public static void main(String[] args) {
Component root = new Composite("root");
Component branchA = new Composite("--branchA");
Component branchB = new Composite("--branchB");
Component leafA = new Leaf("----leafA");
Component leafB = new Leaf("----leafB");
Component leafC = new Leaf("----leafC");
root.addChild(branchA);
root.addChild(branchB);
branchA.addChild(leafA);
branchA.addChild(leafB);
branchB.addChild(leafC);
System.out.println(root.hierarchical());
}
//root
//--branchA
//----leafA
//----leafB
//--branchB
//----leafC
3. 改进
上面的案例中叶子节点也具有根节点的方法,这是不符合逻辑的,可以使用组合模式的安全模式,即改变抽象根节点的方法,而其余不变,这样的话根和叶子的责任就明显了
3.1 修改抽象根节点
代码语言:javascript复制public abstract class Component {
protected String name;
public Component(String name) {
this.name = name;
}
}
3.2 文件系统
若是文件系统,那抽象根节点还可以添加下面两个方法
代码语言:javascript复制public boolean isFile() {
return this instanceof Leaf;
}
public boolean isDir() {
return this instanceof Composite;
}