公司的人事管理就是一個(gè)典型的樹狀結(jié)構(gòu),老大,往下一層一層的管理,最后到我們這層小兵,很典型的樹狀結(jié)構(gòu)

今天的任務(wù)就是要把這個(gè)樹狀結(jié)構(gòu)實(shí)現(xiàn)出來,并且還要把它遍歷一遍。
從這個(gè)樹狀結(jié)構(gòu)上分析,有兩種節(jié)點(diǎn):有分支的節(jié)點(diǎn)(如研發(fā)部經(jīng)理)和無分支的節(jié)點(diǎn)(如員工 A、員工 D 等),我們?cè)黾右稽c(diǎn)學(xué)術(shù)術(shù)語上去,總經(jīng)理叫做根節(jié)點(diǎn)(是不是想到 XML 中的那個(gè)根節(jié)點(diǎn) root,那就對(duì)了),類似研發(fā)部經(jīng)理有分支的節(jié)點(diǎn)叫做樹枝節(jié)點(diǎn),類似員工 A 的無分支的節(jié)點(diǎn)叫做樹葉節(jié)點(diǎn)。

定義一個(gè)根節(jié)點(diǎn),就為總經(jīng)理服務(wù)
public interface IRoot {
????//得到總經(jīng)理的信息
????public String getInfo();
????//總經(jīng)理下邊要有小兵,那要能增加小兵,比如研發(fā)部總經(jīng)理,這是個(gè)樹枝節(jié)點(diǎn)
????public void add(IBranch branch);
????//那要能增加樹葉節(jié)點(diǎn)
????public void add(ILeaf leaf);
????//既然能增加,那要還要能夠遍歷,不可能總經(jīng)理不知道他手下有哪些人
????public ArrayList getSubordinateInfo();
}
根節(jié)點(diǎn)的實(shí)現(xiàn)類
public class Root implements IRoot {
????//保存根節(jié)點(diǎn)下的樹枝節(jié)點(diǎn)和樹葉節(jié)點(diǎn),Subordinate的意思是下級(jí)
????private ArrayList subordinateList = new ArrayList();
????//根節(jié)點(diǎn)的名稱
????private String name = "";
????//根節(jié)點(diǎn)的職位
????private String position = "";
????//根節(jié)點(diǎn)的薪水
????private int salary = 0;
????//通過構(gòu)造函數(shù)傳遞進(jìn)來總經(jīng)理的信息
????public Root(String name,String position,int salary){
????????this.name = name;
????????this.position = position;
????????this.salary = salary;
????}
????//增加樹枝節(jié)點(diǎn)
????public void add(IBranch branch) {
????????this.subordinateList.add(branch);
????}
????//增加葉子節(jié)點(diǎn),比如秘書,直接隸屬于總經(jīng)理
????public void add(ILeaf leaf) {
????????this.subordinateList.add(leaf);
????}
????//得到自己的信息
????public String getInfo() {
????????String info = "";
????????info = "名稱:"+ this.name;;
????????info = info + "\t職位:" + this.position;
????????info = info + "\t薪水: " + this.salary;
????????return info;
????}
????//得到下級(jí)的信息
????public ArrayList getSubordinateInfo() {
????????return this.subordinateList;
????}
}
很簡(jiǎn)單,通過構(gòu)造函數(shù)傳入?yún)?shù),然后獲得信息,還可以增加子樹枝節(jié)點(diǎn)(部門經(jīng)理)和葉子節(jié)點(diǎn)(秘書)
樹枝節(jié)點(diǎn),也就是各個(gè)部門經(jīng)理和組長(zhǎng)的角色
public interface IBranch {
????//獲得信息
????public String getInfo();
????//增加數(shù)據(jù)節(jié)點(diǎn),例如研發(fā)部下的研發(fā)一組
????public void add(IBranch branch);
????//增加葉子節(jié)點(diǎn)
????public void add(ILeaf leaf);
????//獲得下級(jí)信息
????public ArrayList getSubordinateInfo();
}
所有的樹枝節(jié)點(diǎn)
public class Branch implements IBranch {
????//存儲(chǔ)子節(jié)點(diǎn)的信息
????private ArrayList subordinateList = new ArrayList();
????//樹枝節(jié)點(diǎn)的名稱
????private String name="";
????//樹枝節(jié)點(diǎn)的職位
????private String position = "";
????//樹枝節(jié)點(diǎn)的薪水
????private int salary = 0;
????//通過構(gòu)造函數(shù)傳遞樹枝節(jié)點(diǎn)的參數(shù)
????public Branch(String name,String position,int salary){
????????this.name = name;
????????this.position = position;
????????this.salary = salary;
????}
????//增加一個(gè)子樹枝節(jié)點(diǎn)
????public void add(IBranch branch) {
????????this.subordinateList.add(branch);
????}
????//增加一個(gè)葉子節(jié)點(diǎn)
????public void add(ILeaf leaf) {
????????this.subordinateList.add(leaf);
????}
????//獲得自己樹枝節(jié)點(diǎn)的信息
????public String getInfo() {
????????String info = "";
????????info = "名稱:" + this.name;
????????info = info + "\t職位:"+ this.position;
????????info = info + "\t薪水:"+this.salary;
????????return info;
????}
????//獲得下級(jí)的信息
????public ArrayList getSubordinateInfo() {
????????return this.subordinateList;
????}
}
葉子節(jié)點(diǎn),也就是最小的小兵了,只能自己干活,不能指派別人了
public interface ILeaf {
????//獲得自己的信息呀
????public String getInfo();
}
public class Leaf implements ILeaf {
????//葉子叫什么名字
????private String name = "";
????//葉子的職位
????private String position = "";
????//葉子的薪水
????private int salary=0;
????//通過構(gòu)造函數(shù)傳遞信息
????public Leaf(String name,String position,int salary){
????????this.name = name;
????????this.position = position;
????????this.salary = salary;
????}
????//最小的小兵只能獲得自己的信息了
????public String getInfo() {
????????String info = "";
????????info = "名稱:" + this.name;
????????info = info + "\t職位:"+ this.position;
????????info = info + "\t薪水:"+this.salary;
????????return info;
????}
}
好了,所有的根節(jié)點(diǎn),樹枝節(jié)點(diǎn)和葉子節(jié)點(diǎn)都已經(jīng)實(shí)現(xiàn)了,從總經(jīng)理、部門經(jīng)理到最終的員工都已經(jīng)實(shí)現(xiàn)了,然后的工作就是組裝成一個(gè)樹狀結(jié)構(gòu)和遍歷這個(gè)樹狀結(jié)構(gòu)
public class Client {
????public static void main(String[] args) {
????????//首先產(chǎn)生了一個(gè)根節(jié)點(diǎn)
????????IRoot ceo = new Root("王大麻子","總經(jīng)理",100000);
????????//產(chǎn)生三個(gè)部門經(jīng)理,也就是樹枝節(jié)點(diǎn)
????????IBranch developDep = new Branch("劉大瘸子","研發(fā)部門經(jīng)理",10000);
????????IBranch salesDep = new Branch("馬二拐子","銷售部門經(jīng)理",20000);
????????IBranch financeDep = new Branch("趙三駝子","財(cái)務(wù)部經(jīng)理",30000);
????????//再把三個(gè)小組長(zhǎng)產(chǎn)生出來
????????IBranch firstDevGroup = new Branch("楊三乜斜","開發(fā)一組組長(zhǎng)",5000);
????????IBranch secondDevGroup = new Branch("吳大棒槌","開發(fā)二組組長(zhǎng)",6000);
????????//剩下的及時(shí)我們這些小兵了,就是路人甲,路人乙
????????ILeaf a = new Leaf("a","開發(fā)人員",2000);
????????ILeaf b = new Leaf("b","開發(fā)人員",2000);
????????ILeaf c = new Leaf("c","開發(fā)人員",2000);
????????ILeaf d = new Leaf("d","開發(fā)人員",2000);
????????ILeaf e = new Leaf("e","開發(fā)人員",2000);
????????ILeaf f = new Leaf("f","開發(fā)人員",2000);
????????ILeaf g = new Leaf("g","開發(fā)人員",2000);
????????ILeaf h = new Leaf("h","銷售人員",5000);
????????ILeaf i = new Leaf("i","銷售人員",4000);
????????ILeaf j = new Leaf("j","財(cái)務(wù)人員",5000);
????????ILeaf k = new Leaf("k","CEO秘書",8000);
????????ILeaf zhengLaoLiu = new Leaf("鄭老六","研發(fā)部副總",20000);
????????//該產(chǎn)生的人都產(chǎn)生出來了,然后我們?cè)趺唇M裝這棵樹
????????//首先是定義總經(jīng)理下有三個(gè)部門經(jīng)理
????????ceo.add(developDep);
????????ceo.add(salesDep);
????????ceo.add(financeDep);
????????//總經(jīng)理下還有一個(gè)秘書
????????ceo.add(k);
????????//定義研發(fā)部門 下的結(jié)構(gòu)
????????developDep.add(firstDevGroup);
????????developDep.add(secondDevGroup);
????????//研發(fā)部經(jīng)理下還有一個(gè)副總
????????developDep.add(zhengLaoLiu);
????????//看看開發(fā)兩個(gè)開發(fā)小組下有什么
????????firstDevGroup.add(a);
????????firstDevGroup.add(b);
????????firstDevGroup.add(c);
????????secondDevGroup.add(d);
????????secondDevGroup.add(e);
????????secondDevGroup.add(f);
????????//再看銷售部下的人員情況
????????salesDep.add(h);
????????salesDep.add(i);
????????//最后一個(gè)財(cái)務(wù)
????????financeDep.add(j);
????????//樹狀結(jié)構(gòu)寫完畢,然后我們打印出來
????????System.out.println(ceo.getInfo());
????????//打印出來整個(gè)樹形
????????getAllSubordinateInfo(ceo.getSubordinateInfo());
????}
????//遍歷所有的樹枝節(jié)點(diǎn),打印出信息
????private static void getAllSubordinateInfo(ArrayList subordinateList){
????????int length = subordinateList.size();
????????for(int m=0;m<length;m++){ //定義一個(gè)ArrayList長(zhǎng)度,不要在for循環(huán)中每次計(jì)算
????????????Object s = subordinateList.get(m);
????????????if(s instanceof Leaf){ //是個(gè)葉子節(jié)點(diǎn),也就是員工
????????????????ILeaf employee = (ILeaf)s;
????????????????System.out.println(((Leaf) s).getInfo());
????????????}else{
????????????????IBranch branch = (IBranch)s;
????????????????System.out.println(branch.getInfo());
????????????????//再遞歸調(diào)用
????????????????getAllSubordinateInfo(branch.getSubordinateInfo());
????????????}
????????}
????}
}
如果是在我們的項(xiàng)目中有這樣的程序,肯定是被拉出來做典型的。
getInfo 每個(gè)接口都有為什么不能抽象出來?Root 類和 Branch 類有什么差別?為什么要定義成兩個(gè)接口兩個(gè)類?如果我要加一個(gè)任職期限,你是不是每個(gè)類都需要修改?如果我要后序遍歷(從員工找到他的上級(jí)領(lǐng)導(dǎo))能做嗎?
問題很多,我們一個(gè)一個(gè)解決,先說抽象的問題,確實(shí)可以吧 IBranch 和 IRoot 合并成一個(gè)接口,這個(gè)我們先肯定下來,這是個(gè)比較大的改動(dòng),我們先畫個(gè)類圖:

這個(gè)類圖還是有點(diǎn)問題的,接口的作用是什么?定義共性,那 ILeaf 和 IBranch 是不是也有共性呢?有 getInfo(),我們是不是要把這個(gè)共性也已經(jīng)封裝起來呢?

類圖上有兩個(gè)接口,ICorp 是公司所有人員的信息的接口類,不管你是經(jīng)理還是員工,你都有名字,職位,薪水,這個(gè)定義成一個(gè)接口沒有錯(cuò),IBranch 有沒有必要呢?我們先實(shí)現(xiàn)出來然后再說。
公司類,定義每個(gè)員工都有信息
public interface ICorp {
????//每個(gè)員工都有信息
????public String getInfo();
}
Leaf是樹葉節(jié)點(diǎn),在這里就是我們這些小兵
public class Leaf implements ICorp {
????//小兵也有名稱
????private String name = "";
????//小兵也有職位
????private String position = "";
????//小兵也有薪水,否則誰給你干
????private int salary = 0;
????//通過一個(gè)構(gòu)造函數(shù)傳遞小兵的信息
????public Leaf(String name,String position,int salary){
????????this.name = name;
????????this.position = position;
????????this.salary = salary;
????}
????//獲得小兵的信息
????public String getInfo() {
????????String info = "";
????????info = "姓名:" + this.name;
????????info = info + "\t職位:"+ this.position;
????????info = info + "\t薪水:" + this.salary;
????????return info;
????}
}
些經(jīng)理和小組長(zhǎng)是怎么實(shí)現(xiàn)的,先看接口:
public interface IBranch {?
????//能夠增加小兵(樹葉節(jié)點(diǎn))或者是經(jīng)理(樹枝節(jié)點(diǎn))
????public void addSubordinate(ICorp corp);
????//我還要能夠獲得下屬的信息
????public ArrayList<ICorp> getSubordinate();
}
實(shí)現(xiàn)類:
public class Branch implements IBranch, ICorp {
????//領(lǐng)導(dǎo)也是人,也有名字
????private String name = "";
????//領(lǐng)導(dǎo)和領(lǐng)導(dǎo)不同,也是職位區(qū)別
????private String position = "";
????//領(lǐng)導(dǎo)也是拿薪水的
????private int salary = 0;
????//領(lǐng)導(dǎo)下邊有那些下級(jí)領(lǐng)導(dǎo)和小兵
????ArrayList<ICorp> subordinateList = new ArrayList<ICorp>();
????//通過構(gòu)造函數(shù)傳遞領(lǐng)導(dǎo)的信息
????public Branch(String name,String position,int salary){
????????this.name = name;
????????this.position = position;
????????this.salary = salary;
????}
????//增加一個(gè)下屬,可能是小頭目,也可能是個(gè)小兵
????public void addSubordinate(ICorp corp) {
????????this.subordinateList.add(corp);
????}
????//我有哪些下屬
????public ArrayList<ICorp> getSubordinate() {
????????return this.subordinateList;
????}
????//領(lǐng)導(dǎo)也是人,他也有信息
????public String getInfo() {
????????String info = "";
????????info = "姓名:" + this.name;
????????info = info + "\t職位:"+ this.position;
????????info = info + "\t薪水:" + this.salary;
????????return info;
????}
}
組裝這個(gè)樹形結(jié)構(gòu),并展示出來
public class Client {
????public static void main(String[] args) {
????????//首先是組裝一個(gè)組織結(jié)構(gòu)出來
????????Branch ceo = compositeCorpTree();
????????//首先把CEO的信息打印出來:
????????System.out.println(ceo.getInfo());
????????//然后是所有員工信息
????????System.out.println(getTreeInfo(ceo));
????}
????//把整個(gè)樹組裝出來
????public static Branch compositeCorpTree(){
????????//首先產(chǎn)生總經(jīng)理CEO
????????Branch root = new Branch("王大麻子","總經(jīng)理",100000);
????????//把三個(gè)部門經(jīng)理產(chǎn)生出來
????????Branch developDep = new Branch("劉大瘸子","研發(fā)部門經(jīng)理",10000);
????????Branch salesDep = new Branch("馬二拐子","銷售部門經(jīng)理",20000);
????????Branch financeDep = new Branch("趙三駝子","財(cái)務(wù)部經(jīng)理",30000);
????????//再把三個(gè)小組長(zhǎng)產(chǎn)生出來
????????Branch firstDevGroup = new Branch("楊三乜斜","開發(fā)一組組長(zhǎng)",5000);
????????Branch secondDevGroup = new Branch("吳大棒槌","開發(fā)二組組長(zhǎng)",6000);
????????//把所有的小兵都產(chǎn)生出來
????????Leaf a = new Leaf("a","開發(fā)人員",2000);
????????Leaf b = new Leaf("b","開發(fā)人員",2000);
????????Leaf c = new Leaf("c","開發(fā)人員",2000);
????????Leaf d = new Leaf("d","開發(fā)人員",2000);
????????Leaf e = new Leaf("e","開發(fā)人員",2000);
????????Leaf f = new Leaf("f","開發(fā)人員",2000);
????????Leaf g = new Leaf("g","開發(fā)人員",2000);
????????Leaf h = new Leaf("h","銷售人員",5000);
????????Leaf i = new Leaf("i","銷售人員",4000);
????????Leaf j = new Leaf("j","財(cái)務(wù)人員",5000);
????????Leaf k = new Leaf("k","CEO秘書",8000);
????????Leaf zhengLaoLiu = new Leaf("鄭老六","研發(fā)部副經(jīng)理",20000);
????????//開始組裝
????????//CEO下有三個(gè)部門經(jīng)理和一個(gè)秘書
????????root.addSubordinate(k);
????????root.addSubordinate(developDep);
????????root.addSubordinate(salesDep);
????????root.addSubordinate(financeDep);
????????//研發(fā)部經(jīng)理
????????developDep.addSubordinate(zhengLaoLiu);
????????developDep.addSubordinate(firstDevGroup);
????????developDep.addSubordinate(secondDevGroup);
????????//看看開發(fā)兩個(gè)開發(fā)小組下有什么
????????firstDevGroup.addSubordinate(a);
????????firstDevGroup.addSubordinate(b);
????????firstDevGroup.addSubordinate(c);
????????secondDevGroup.addSubordinate(d);
????????secondDevGroup.addSubordinate(e);
????????secondDevGroup.addSubordinate(f);
????????//再看銷售部下的人員情況
????????salesDep.addSubordinate(h);
????????salesDep.addSubordinate(i);
????????//最后一個(gè)財(cái)務(wù)
????????financeDep.addSubordinate(j);
????????return root;
????}
????//遍歷整棵樹,只要給我根節(jié)點(diǎn),我就能遍歷出所有的節(jié)點(diǎn)
????public static String getTreeInfo(Branch root){
????????ArrayList<ICorp> subordinateList = root.getSubordinate();
????????String info = "";
????????for(ICorp s :subordinateList){
????????????if(s instanceof Leaf){ //是員工就直接獲得信息
????????????????info = info + s.getInfo()+"\n";
????????????}else{ //是個(gè)小頭目
????????????????info = info + s.getInfo() +"\n"+ getTreeInfo((Branch)s);
????????????}
????????}
????????return info;
????}
}
你看 Leaf和 Branch中都有 getInfo 信息,是否可以抽象,好,我們抽象一下:

定義一個(gè)公司的人員的抽象類
public abstract class Corp {
????//公司每個(gè)人都有名稱
????private String name = "";
????//公司每個(gè)人都職位
????private String position = "";
????//公司每個(gè)人都有薪水
????private int salary =0;
????/*通過接口的方式傳遞,我們改變一下習(xí)慣,傳遞進(jìn)來的參數(shù)名以下劃線開始
????* 這個(gè)在一些開源項(xiàng)目中非常常見,一般構(gòu)造函數(shù)都是這么定義的
????*/
????public Corp(String _name,String _position,int _salary){
????????this.name = _name;
????????this.position = _position;
????????this.salary = _salary;
????}
????//獲得員工信息
????public String getInfo(){
????????String info = "";
????????info = "姓名:" + this.name;
????????info = info + "\t職位:"+ this.position;
????????info = info + "\t薪水:" + this.salary;
????????return info;
????}
}
普通員工很簡(jiǎn)單,就寫一個(gè)構(gòu)造函數(shù)就可以了
public class Leaf extends Corp {
????//就寫一個(gè)構(gòu)造函數(shù),這個(gè)是必須的
????public Leaf(String _name,String _position,int _salary){
????????super(_name,_position,_salary);
????}
}
小頭目的實(shí)現(xiàn)類:
public class Branch extends Corp {
????//領(lǐng)導(dǎo)下邊有那些下級(jí)領(lǐng)導(dǎo)和小兵
????ArrayList<Corp> subordinateList = new ArrayList<Corp>();
????//構(gòu)造函數(shù)是必須的了
????public Branch(String _name,String _position,int _salary){
????????super(_name,_position,_salary);
????}
????//增加一個(gè)下屬,可能是小頭目,也可能是個(gè)小兵
????public void addSubordinate(Corp corp) {
????????this.subordinateList.add(corp);
????}
????//我有哪些下屬
????public ArrayList<Corp> getSubordinate() {
????????return this.subordinateList;
????}
}
組裝這個(gè)樹形結(jié)構(gòu),并展示出來
public class Client {
????public static void main(String[] args) {
????????//首先是組裝一個(gè)組織結(jié)構(gòu)出來
????????Branch ceo = compositeCorpTree();
????????//首先把CEO的信息打印出來:
????????System.out.println(ceo.getInfo());
????????//然后是所有員工信息
????????System.out.println(getTreeInfo(ceo));
????}
????//把整個(gè)樹組裝出來
????public static Branch compositeCorpTree(){
????????//首先產(chǎn)生總經(jīng)理CEO
????????Branch root = new Branch("王大麻子","總經(jīng)理",100000);
????????//把三個(gè)部門經(jīng)理產(chǎn)生出來
????????Branch developDep = new Branch("劉大瘸子","研發(fā)部門經(jīng)理",10000);
????????Branch salesDep = new Branch("馬二拐子","銷售部門經(jīng)理",20000);
????????Branch financeDep = new Branch("趙三駝子","財(cái)務(wù)部經(jīng)理",30000);
????????//再把三個(gè)小組長(zhǎng)產(chǎn)生出來
????????Branch firstDevGroup = new Branch("楊三乜斜","開發(fā)一組組長(zhǎng)",5000);
????????Branch secondDevGroup = new Branch("吳大棒槌","開發(fā)二組組長(zhǎng)",6000);
????????//把所有的小兵都產(chǎn)生出來
????????Leaf a = new Leaf("a","開發(fā)人員",2000);
????????Leaf b = new Leaf("b","開發(fā)人員",2000);
????????Leaf c = new Leaf("c","開發(fā)人員",2000);
????????Leaf d = new Leaf("d","開發(fā)人員",2000);
????????Leaf e = new Leaf("e","開發(fā)人員",2000);
????????Leaf f = new Leaf("f","開發(fā)人員",2000);
????????Leaf g = new Leaf("g","開發(fā)人員",2000);
????????Leaf h = new Leaf("h","銷售人員",5000);
????????Leaf i = new Leaf("i","銷售人員",4000);
????????Leaf j = new Leaf("j","財(cái)務(wù)人員",5000);
????????Leaf k = new Leaf("k","CEO秘書",8000);
????????Leaf zhengLaoLiu = new Leaf("鄭老六","研發(fā)部副經(jīng)理",20000);
????????//開始組裝
????????//CEO下有三個(gè)部門經(jīng)理和一個(gè)秘書
????????root.addSubordinate(k);
????????root.addSubordinate(developDep);
????????root.addSubordinate(salesDep);
????????root.addSubordinate(financeDep);
????????//研發(fā)部經(jīng)理
????????developDep.addSubordinate(zhengLaoLiu);
????????developDep.addSubordinate(firstDevGroup);
????????developDep.addSubordinate(secondDevGroup);
????????//看看開發(fā)兩個(gè)開發(fā)小組下有什么
????????firstDevGroup.addSubordinate(a);
????????firstDevGroup.addSubordinate(b);
????????firstDevGroup.addSubordinate(c);
????????secondDevGroup.addSubordinate(d);
????????secondDevGroup.addSubordinate(e);
????????secondDevGroup.addSubordinate(f);
????????//再看銷售部下的人員情況
????????salesDep.addSubordinate(h);
????????salesDep.addSubordinate(i);
????????//最后一個(gè)財(cái)務(wù)
????????financeDep.addSubordinate(j);
????????return root;
????}
????//遍歷整棵樹,只要給我根節(jié)點(diǎn),我就能遍歷出所有的節(jié)點(diǎn)
????public static String getTreeInfo(Branch root){
????????ArrayList<Corp> subordinateList = root.getSubordinate();
????????String info = "";
????????for(Corp s :subordinateList){
????????????if(s instanceof Leaf){ //是員工就直接獲得信息
????????????????info = info + s.getInfo()+"\n";
????????????}else{ //是個(gè)小頭目
????????????????info = info + s.getInfo() +"\n"+ getTreeInfo((Branch)s);
????????????}
????????}
????????return info;
????}
}
組合模式通用類圖如下:

我們先來說說組合模式的幾個(gè)角色:
抽象構(gòu)件角色(Component):定義參加組合的對(duì)象的共有方法和屬性,可以定義一些默認(rèn)的行為或?qū)傩?;比如我們例子中?getInfo 就封裝到了抽象類中。
葉子構(gòu)件(Leaf):葉子對(duì)象,其下再也沒有其他的分支。
樹枝構(gòu)件(Composite):樹枝對(duì)象,它的作用是組合樹枝節(jié)點(diǎn)和葉子節(jié)點(diǎn);
組合模式有兩種模式,透明模式和安全模式,這兩個(gè)模式有什么區(qū)別呢?先看類圖:


從類圖上大家應(yīng)該能看清楚了,這兩種模式各有優(yōu)缺點(diǎn),透明模式是把用來組合使用的方法放到抽象類中,比如 add(),remove()以及 getChildren 等方法(順便說一下,getChildren 一般返回的結(jié)果為 Iterable的實(shí)現(xiàn)類,很多,大家可以看 JDK 的幫助),不管葉子對(duì)象還是樹枝對(duì)象都有相同的結(jié)構(gòu),通過判斷是getChildren 的返回值確認(rèn)是葉子節(jié)點(diǎn)還是樹枝節(jié)點(diǎn),如果處理不當(dāng),這個(gè)會(huì)在運(yùn)行期出現(xiàn)問題的,不是很建議的方式;安全模式就不同了,它是把樹枝節(jié)點(diǎn)和樹葉節(jié)點(diǎn)徹底分開,樹枝節(jié)點(diǎn)單獨(dú)擁有用來組合的方法,這種方法比較安全,我們的例子使用了安全模式。
第一個(gè)優(yōu)點(diǎn)只要是樹形結(jié)構(gòu),就要考慮使用組合模式。
我們?cè)谏厦嬉策€提到了一個(gè)問題,就是樹的遍歷問題,從上到下遍歷沒有問題,但是我要是從下往上遍歷呢?

定義一個(gè)公司的人員的抽象類
public abstract class Corp {
????//公司每個(gè)人都有名稱
????private String name = "";
????//公司每個(gè)人都職位
????private String position = "";
????//公司每個(gè)人都有薪水
????private int salary =0;
????//父節(jié)點(diǎn)是誰
????private Corp parent = null;
????/*通過接口的方式傳遞,我們改變一下習(xí)慣,傳遞進(jìn)來的參數(shù)名以下劃線開始
????* 這個(gè)在一些開源項(xiàng)目中非常常見,一般構(gòu)造函數(shù)都是定義的
????*/
????public Corp(String _name,String _position,int _salary){
????????this.name = _name;
????????this.position = _position;
????????this.salary = _salary;
????}
????//獲得員工信息
????public String getInfo(){
????????String info = "";
????????info = "姓名:" + this.name;
????????info = info + "\t職位:"+ this.position;
????????info = info + "\t薪水:" + this.salary;
????????return info;
????}
????//設(shè)置父節(jié)點(diǎn)
????protected void setParent(Corp _parent){
????????this.parent = _parent;
????}
????//得到父節(jié)點(diǎn)
????public Corp getParent(){
????????return this.parent;
????}
}
節(jié)點(diǎn)類:
public class Branch extends Corp {
????//領(lǐng)導(dǎo)下邊有那些下級(jí)領(lǐng)導(dǎo)和小兵
????ArrayList<Corp> subordinateList = new ArrayList<Corp>();
????//構(gòu)造函數(shù)是必須的了
????public Branch(String _name,String _position,int _salary){
????????super(_name,_position,_salary);
????}
????//增加一個(gè)下屬,可能是小頭目,也可能是個(gè)小兵
????public void addSubordinate(Corp corp) {
????????corp.setParent(this); //設(shè)置父節(jié)點(diǎn)
????????this.subordinateList.add(corp);
????}
????//我有哪些下屬
????public ArrayList<Corp> getSubordinate() {
????????return this.subordinateList;
????}
}