組合模式:將對象組合成樹形結構以表示“部分-整體”的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。· 意思就是用樹狀結構來表示部分和整體,使他們具有一致性,一致性的意思就是都實現了相同的介面,舉個例子,一個公司可能有研發部門和銷售部門,然後這個公司又有子公司,子公司也有研發和銷售部 ...
組合模式:將對象組合成樹形結構以表示“部分-整體”的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。·
意思就是用樹狀結構來表示部分和整體,使他們具有一致性,一致性的意思就是都實現了相同的介面,舉個例子,一個公司可能有研發部門和銷售部門,然後這個公司又有子公司,子公司也有研發和銷售部門,不論是總公司的部門還是子公司的部門,他們的職責其實是差不多的,當我們希望總公司的部門的職責複製到子公司時,就可以使用組合模式。我們看以下代碼
//公司介面 public interface Company { void add(Company company); void remove(Company company); //展示樹形結構 void display(int depth); //不同部門所具有的各自的職責 void duty(); }
// 具體公司類 樹枝節點 public class ConcreteCompany implements Company { private List<Company> companyList = new ArrayList<>(); private String name; public ConcreteCompany(String name){ this.name = name; } @Override public void add(Company company) { companyList.add(company); } @Override public void remove(Company company) { companyList.remove(company); } @Override public void display(int depth) { StringBuffer stringBuffer = new StringBuffer("-"); for (int i = 0; i < depth ; i++) { stringBuffer.append("-"); } System.out.println(stringBuffer.append(name)); for (Company company: companyList) { company.display(depth+2); } } @Override public void duty() { for (Company company:companyList) { company.duty(); } } }
//部門類1 葉子節點 public class Department1 implements Company { private String name; public Department1(String name){ this.name = name; } @Override public void add(Company company) { } @Override public void remove(Company company) { } @Override public void display(int depth) { StringBuffer stringBuffer = new StringBuffer("-"); for (int i = 0; i < depth ; i++) { stringBuffer.append("-"); } System.out.println(stringBuffer.append(name)); } @Override public void duty() { System.out.println(name + "負責研發產品"); } }
//部門類2 葉子節點 public class Department2 implements Company { private String name; public Department2(String name){ this.name = name; } @Override public void add(Company company) { } @Override public void remove(Company company) { } @Override public void display(int depth) { StringBuffer stringBuffer = new StringBuffer("-"); for (int i = 0; i < depth ; i++) { stringBuffer.append("-"); } System.out.println(stringBuffer.append(name)); } @Override public void duty() { System.out.println(name + "負責銷售"); } }
public class Test { public static void main(String[] args) { //根節點 ConcreteCompany root = new ConcreteCompany("總公司"); root.add(new Department1("總公司部門1")); root.add(new Department2("總公司部門2")); //子節點 ConcreteCompany comp = new ConcreteCompany("分公司"); comp.add(new Department1("分公司部門1")); comp.add(new Department2("分公司部門2")); root.add(comp); //葉子節點1 ConcreteCompany comp1 = new ConcreteCompany("辦事處1"); comp1.add(new Department1("辦事處1部門1")); comp1.add(new Department2("辦事處1部門2")); comp.add(comp1); //葉子節點2 ConcreteCompany comp2 = new ConcreteCompany("辦事處2"); comp2.add(new Department1("辦事處2部門1")); comp2.add(new Department2("辦事處2部門2")); comp.add(comp2); root.display(1); root.duty(); } }
測試結果:
--總公司
----總公司部門1
----總公司部門2
----分公司
------分公司部門1
------分公司部門2
------辦事處1
--------辦事處1部門1
--------辦事處1部門2
------辦事處2
--------辦事處2部門1
--------辦事處2部門2
總公司部門1負責研發產品
總公司部門2負責銷售
分公司部門1負責研發產品
分公司部門2負責銷售
辦事處1部門1負責研發產品
辦事處1部門2負責銷售
辦事處2部門1負責研發產品
辦事處2部門2負責銷售
總結:從測試結果我們可以看到不同父節點的子節點相同的部門的職責是一樣的,除此之外我們可以發現葉子節點實現了add()和remove()方法,因為這樣葉子節點和其他節點對於外界沒有區別,它們具有完全一致的行為介面,但是問題就是葉子節點是最底層的分支節點,實現添加和刪除是沒有意義的,給客戶端帶來了不安全性,這種方式就是透明方式。我們也可以在Company介面中不去聲明這兩個方法,這樣安全性得到了提高,但是與此相對變得不再透明,樹葉和樹枝將不再具有相同的介面,客戶端調用時就需要做相對應的判斷。 當需求中體現整體與部分的層次結構,並且用戶希望可以忽略組合對象與單個對象的不同,統一使用組合結構的所有對象時,我們就可以考慮使用組合模式。