設(shè)計(jì)模式之禪-組合模式

公司的人事管理就是一個(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;

????}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概述 UML類圖 代碼栗子 總結(jié) 概述概念 組合模式是指將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),組合模...
    tanoak閱讀 419評(píng)論 0 0
  • 大家在上學(xué)的時(shí)候應(yīng)該都學(xué)過“數(shù)據(jù)結(jié)構(gòu)”這門課程吧,還記得其中有一節(jié)叫“二叉樹”吧,我們上學(xué)那會(huì)兒這一章節(jié)是必考內(nèi)容...
    遼A丶孫悟空閱讀 267評(píng)論 0 8
  • Composite 模式 一、描述 概念:將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。 Composite...
    卡爾曼閱讀 408評(píng)論 0 0
  • 結(jié)構(gòu)型設(shè)計(jì)模式 12.組合模式 組合模式又稱“整體-部分”設(shè)計(jì)模式,讓整體與部分的使用具有一致性。 12.1創(chuàng)建抽...
    crazyydevil閱讀 157評(píng)論 0 0
  • 個(gè)人學(xué)習(xí)筆記分享,當(dāng)前能力有限,請(qǐng)勿貶低,菜鳥互學(xué),大佬繞道如有勘誤,歡迎指出和討論,本文后期也會(huì)進(jìn)行修正和補(bǔ)充 ...
    Echo_YeZ閱讀 587評(píng)論 0 0

友情鏈接更多精彩內(nèi)容