組合模式屬於結構型模式java
將組合模式合成樹形結構以表示「部分-總體」 的層次結構。「Composite」使得用戶對單個對象和組合對象的使用具備一致性。程序員
適用性:編程
你想表示對象的部分-總體層次結構。安全
你但願用戶忽略組合對象與單個對象的不一樣,用戶將統一地使用組合結構中的全部對象。ide
結構:測試
Component 爲組合中的對象聲明接口。在適當狀況下,實現全部類共有接口的缺省行爲。聲明一個接口用於訪問和管理component的子組件。this
leaf 在組合中表示葉節點對象,葉節點沒有子節點。spa
composite 定義有子部件的那些不見的行爲。存儲子部件。在component接口中實現與子部件有關的操做。code
client接口操做組合不見的對象。component
組合模式分爲透明模式和安全模式
透明模式:在Component中聲明全部用來管 理子對象的方法,如Add()方法,Remove()方法及GetChild()方法,全部實現Component接口的子類都具有這些方法,這使得 Component和子類具有一致的行爲接口,使得對客戶端無需區別樹葉和樹枝對象。
安全模式: 在透明模式基礎上把Component中聲明全部用來管理子對象的方法移到Composite中,在Composite實現子對象的管理方法,那麼 Leaf就沒有子對象管理方法,這使得Composite和Leaf的行爲接口不一致,因此客戶端在調用時要知道樹葉和樹枝對象存在。
組合模式符合開放封閉原則,迪米特法則。
組合模式優勢
高層模塊調用簡單:一棵屬性結構中全部節點都是component,局部和總體對調用者來講沒有任何區別,也就是說,高層模塊沒必要關心本身處理的是單個對象仍是整個組合結構,簡化了高層模塊的代碼。
節點自由增長:使用組合模式後,若是想增長一個樹枝節點,樹葉節點,只要找到它的父節點set進去就能夠。對之後維護很是簡單。
組合模式缺點
樹枝和樹葉的實現中直接使用了實現類,這在面向接口編程上是很不恰當的,與依賴倒置原則衝突。
經過繼承來實現的結構型模式,必定要當心子類覆蓋父類方法,由於這樣可能致使整個結構的功能發生難以預知的變化。
應用場景:
維護一個樹形菜單,文件系統等。
1.下述代碼是一種透明模式的組合模式
public class ZuhemoshiTest { public static void main(String[] args) { Employer employer=new ProjectManager("項目經理"); Employer employer2=new Programer("程序員1"); Employer employer3=new Programer("程序員2"); employer.add(employer2); employer.add(employer3); } } abstract class Employer{ private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public abstract void add(Employer employer); public abstract void delete(Employer employer); public List<Employer> employers; public void printInfo(){ System.out.println(name); } public List<Employer> getEmployers(){ return employers; } public void displayTree(Employer root) {//遞歸遍歷整個樹。 List<Employer> children = root.getEmployers(); for (Employer employer : children) { System.out.println(employer.getName()); if(employer.getEmployers()!=null){ for(Employer employer2:employer.getEmployers()){ displayTree(employer2); } } } } } class Programer extends Employer{//至關於leaf public Programer(String name){ setName(name); employers=null;//最低端的程序員,能僱傭的只有腦子T T } @Override public void add(Employer employer) { } @Override public void delete(Employer employer) { } } class ProjectManager extends Employer{ public ProjectManager(String name){ setName(name); employers=new ArrayList<Employer>(); } @Override public void add(Employer employer) { employers.add(employer); } @Override public void delete(Employer employer) { employers.remove(employer); } }
上述代碼定義了一個樹形結構,假如咱們想定義一個employer的動做,只須要在父類中定義,所有子類重寫或者直接繼承便可。
2.安全模式測試代碼
public class ZuhemoshiTest { public static void main(String[] args) { Manager manager=new ProjectManager("項目經理"); Employer employer2=new Programer("程序員1"); Employer employer3=new Programer("程序員2"); manager.add(employer2); manager.add(employer3); } } class Employer{ protected String name; public void setName(String name) { this.name = name; } public String getName() { return name; } } class Programer extends Employer{//至關於leaf public Programer(String name){ setName(name); } } abstract class Manager extends Employer{ public abstract void add(Employer employer); public abstract void delete(Employer employer); public List<Employer> employers; public void printInfo(){ System.out.println(name); } public List<Employer> getEmployers(){ return employers; } public void displayTree(Manager root) { List<Employer> children = root.getEmployers(); for (Employer employer : children) { if(employer instanceof Manager){ System.out.println(employer.getName()); displayTree((Manager)employer); }else { System.out.println(employer.getName()); } } } } class ProjectManager extends Manager{ public ProjectManager(String name){ setName(name); employers=new ArrayList<Employer>(); } @Override public void add(Employer employer) { employers.add(employer); } @Override public void delete(Employer employer) { employers.remove(employer); } }
3.爲了應對組合模式沒有實現面向接口編程,我的認爲能夠經過接口實現。核心代碼以下,這個相關資料裏沒有提到過,不知道對不對。歡迎大神指正。
interface Employ{ public List<Employ> employs=new ArrayList<Employ>();//接口中聲明的變量是final的,表示變量地址不會改變 void add(Employ employ); void remove(Employ employ); }