天天看點

組合模式

暫時還沒遇到需要這種設計模式的情景,筆者一般會把層次結構放到資料庫裡,用 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;
}