暫時還沒遇到需要這種設計模式的情景,筆者一般會把層次結構放到資料庫裡,用 parentId 來辨別父子關系
1. 組合模式(Composite Pattern)
将對象組合成樹形結構以表示 “部分-整體” 的層次結構,使得使用者對單個對象群組合對象的使用具有一緻性
組合模式的組成:
- 抽象根節點(Component):存放整體的預設行為和屬性
- 樹枝節點(Composite):存儲葉子節點的集合
- 葉子節點(Leaf):存放真實對象
2. 流程
這裡很像作業系統的檔案結構
2.1 Component
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
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
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 案例
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 修改抽象根節點
public abstract class Component {
protected String name;
public Component(String name) {
this.name = name;
}
}
3.2 檔案系統
若是檔案系統,那抽象根節點還可以添加下面兩個方法
public boolean isFile() {
return this instanceof Leaf;
}
public boolean isDir() {
return this instanceof Composite;
}