組合模式

eacape發表於2020-10-18

將物件組合成樹狀結構以表示整個部分的層次結構,組合模式可以讓使用者統一對待單個物件和物件組合。

組合模式一般可以分三個角色

  • 抽象元件:定義需要實現的統一操作
  • 組合節點:一個可以包含多個物件的複合物件,意味著它下面可能還會有其它組合節點和葉子節點
  • 葉子節點:下面不會有其它節點(與組合幾點唯一的差距就是沒有子節點)

組合模式最常用的就是用來表示一些樹形結構的物件關係,就比如說部門或者員工之間的上下級關係。

下面通過員工上下級關係的例子來實現一個組合模式

抽象元件,裡面定義了一些節點的共同屬性和方法

public abstract class AbstractNode {
    private String name;
    private AbstractNode parent;

    public AbstractNode(String name) {
        this.name = name;
    }

    public AbstractNode getParent() {
        return parent;
    }

    public void setParent(AbstractNode parent) {
        this.parent = parent;
    }

    public String getName(){
        return name;
    }

    public abstract void addChild(AbstractNode node);
    public abstract AbstractNode getChild(int i);
    public abstract void removeChild(int i);

    /**
     * 員工自我介紹
     */
    public abstract void introduce();

    /**
     * 團隊統計
     */
    public abstract int teamCount();
}

組合節點相當於領導層,它們下面會管理一些員工

public class Node extends AbstractNode{
    private List<AbstractNode> nodes;
    public Node(String name) {
        super(name);
        nodes = new ArrayList<>();
    }

    @Override
    public void addChild(AbstractNode node) {
        node.setParent(this);
        nodes.add(node);
    }

    @Override
    public AbstractNode getChild(int i) {
        return nodes.get(i);
    }

    @Override
    public void removeChild(int i) {
        nodes.remove(i);
    }

    @Override
    public void introduce() {
        String parentName = getParent()==null?" null":getParent().getName();
        System.out.println("I am "+getName()+",my parent is "+parentName+
        ",I have "+nodes.size()+" child.");
        for (AbstractNode node:nodes) {
            node.introduce();
        }
    }

    @Override
    public int teamCount() {
        int count = 0;
        for (AbstractNode node:nodes) {
           count += node.teamCount();
        }
        return count + 1;
    }


}

葉子節點,相當於底層員工,它們相隨與組合節點更加簡單

public class Leaf extends AbstractNode{
    public Leaf(String name) {
        super(name);
    }

    @Override
    public void addChild(AbstractNode node) {
        throw new RuntimeException("這是葉子節點");
    }

    @Override
    public AbstractNode getChild(int i) {
        throw new RuntimeException("這是葉子節點");
    }

    @Override
    public void removeChild(int i) {
        throw new RuntimeException("這是葉子節點");
    }

    @Override
    public void introduce() {
        System.out.println("I am "+getName()+",my parent is "+getParent().getName()+".");
    }

    @Override
    public int teamCount() {
        return 1;
    }
}

客戶端呼叫

public class Client {
    public static void main(String[] args) {
        AbstractNode head = new Node("大領導");
        AbstractNode midA = new Node("小領導A");
        AbstractNode midB = new Node("小領導B");
        AbstractNode staff1 = new Leaf("員工-1");
        AbstractNode staff2 = new Leaf("員工-2");
        AbstractNode staff3 = new Leaf("員工-3");

        head.addChild(midA);
        head.addChild(midB);
        midA.addChild(staff1);
        midA.addChild(staff2);
        midB.addChild(staff3);

        head.introduce();
        System.out.println(head.getName()+"一共領導"+head.teamCount()+"人");
        System.out.println(midA.getName()+"一共領導"+midA.teamCount()+"人");

    }
}
==========結果==========
I am 大領導,my parent is  null,I have 2 child.
I am 小領導A,my parent is 大領導,I have 2 child.
I am 員工-1,my parent is 小領導A.
I am 員工-2,my parent is 小領導A.
I am 小領導B,my parent is 大領導,I have 1 child.
I am 員工-3,my parent is 小領導B.
大領導一共領導6人
小領導A一共領導3人

組合模式的主要目的是可以通過物件之間的組合關係把一組物件當作一個整體,統一操作。

相關文章