组合模式--分公司=一部门

  组合模式:将对象组合成树形接口以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
  

  为什么Leaf类中也有add和remove,树叶不是不可以再长分支吗?
        是的,这种方式叫做透明方式,也就是说在Component中声明所有用来管理子对象的方法啊,其中包括add、remove等。这样实现Component接口的所有子类都具备了add和remove。这样做的好处就是叶节点和枝节点对于外界没有区别,他们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备add()、remve()方法的功能,所以实现它是没有意义的。
        如果我不希望Leaf类中用add和remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所以树叶和树枝将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。
        
  透明方式,那样就不用做任何判断了。


    应用场景:当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。
    组合模式让客户可以一致地使用组合结构和单个对象。

 

 1 /**
 2  * Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。
 3  *     声明一个接口用于访问和管理Component的子部件
 4  * @author 贤元
 5  *
 6  */
 7 public abstract class Component {
 8     protected String name;
 9     public Component(String name){
10         this.name = name;
11     }
12     
13     public abstract void add(Component c);
14     public abstract void remove(Component c);
15     public abstract void display(int depth);
16 }

 

 

 1 /**
 2  * Component定义有枝节点行为,用来存储子部件,
 3  *     在Component接口中实现与子部件有关的操作,比如增加add和删除remove
 4  * @author 贤元
 5  *
 6  */
 7 public class Composite extends Component {
 8     
 9     private List<Component> children = new LinkedList<Component>();
10     
11     public Composite(String name) {
12         super(name);
13         // TODO Auto-generated constructor stub
14     }
15 
16     @Override
17     public void add(Component c) {
18         children.add(c);
19     }
20 
21     @Override
22     public void remove(Component c) {
23         children.remove(c);
24     }
25 
26     @Override
27     public void display(int depth) {
28         String str = "";//用于拼接'-',depth表示多少,就拼接多少个'-',用于显示效果
29         for(int i=0;i<depth;i++){
30             str += "-";
31         }
32         System.out.println(str+name);
33         
34         for(Component component:children){
35             component.display((depth+2));
36         }
37     }
38 
39 }

 

 1 public class Leaf extends Component{
 2     
 3     public Leaf(String name) {
 4         super(name);
 5         // TODO Auto-generated constructor stub
 6     }
 7 
 8     /**
 9      * 由于叶子没有再增加分支和树叶,所以add和remove实现它没有意义,
10      *     但这样做可以消除叶节点和枝节点对象在抽象层次的区别,他们具备完全一致的接口。
11      */
12     @Override
13     public void add(Component c) {
14         System.out.println("Cannot add to a leaf"); 
15     }
16 
17     @Override
18     public void remove(Component c) {
19         System.out.println("Cannot remove from a leaf");
20     }
21 
22     //叶节点的具体方法,此处是显示其名称和级别
23     @Override
24     public void display(int depth) {
25         String str = "";////用于拼接'-',depth表示多少,就拼接多少个'-',用于显示效果
26         for(int i=0;i<depth;i++){
27             str += "-";
28         }
29         System.out.println(str+name);
30     }
31 }

 

 

 1 public class TestClient {
 2     public static void main(String[] args) {
 3         //生成树根root,根上长出两叶LeafA和LeafB
 4         Component root = new Composite("root");
 5         root.add(new Leaf("Leaf A"));
 6         root.add(new Leaf("Leaf B"));
 7         
 8         //根上长出分支CompositeX,分支上也有两叶LeafXA和LeafXB
 9         Composite comp = new Composite("Composite A");
10         comp.add(new Leaf("Leaf XA"));
11         comp.add(new Leaf("Leaf XB"));
12         
13         root.add(comp);
14         
15         //在CompositeX上再长出分支CompositeXY,分支上也有两叶LeafXYA和LeafXYB
16         Composite comp2 = new Composite("Composite XY");
17         comp2.add(new Leaf("Leaf XYA"));
18         comp2.add(new Leaf("Leaf XYB"));
19         
20         comp.add(comp2);
21         
22         root.add(new Leaf("Leaf C"));
23         
24         //根部又长出两叶LeafC和LeafD,可惜LeafD没长牢,被风吹走了
25         Leaf leaf = new Leaf("Leaf D");
26         root.add(leaf);
27         root.remove(leaf);
28         
29         //显示大树的样子
30         root.display(1);
31         
32     }
33 }

打印结果:

-root
---Leaf A
---Leaf B
---Composite A
-----Leaf XA
-----Leaf XB
-----Composite XY
-------Leaf XYA
-------Leaf XYB
---Leaf C

UML图:

  

 

 

 

一个例子:

  组合模式定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。用户不关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。组合模式让客户可以一致地使用组合结构和单个对象。
    只要写一套代码,就可以在不同层次级别中使用,而不用对不同层次的再重复开发一套代码

  

 1 //公司类,抽象类或接口
 2 public abstract class Company {
 3     protected String name;
 4     
 5     public Company(String name){
 6         this.name = name;
 7     }
 8     
 9     public abstract void add(Company c);//增加
10     public abstract void remove(Company c);//移除
11     public abstract void display(int depth);//显示
12     public abstract void lineOfDuty();//履行职责
13 }

 

 

 1 //具体公司类,实现接口,树枝节点
 2 public class ConcreteCompany extends Company {
 3 
 4     private List<Company> children = new LinkedList<Company>();
 5     
 6     //构造方法
 7     public ConcreteCompany(String name) {
 8         super(name);
 9     }
10 
11     @Override
12     public void add(Company c) {
13         children.add(c);
14     }
15 
16     @Override
17     public void remove(Company c) {
18         children.remove(c);
19     }
20 
21     @Override
22     public void display(int depth) {
23         String str = "";//用于拼接'-',dept等于多少就表示拼接几个'-',用于显示效果
24         for(int i=0;i<depth;i++){
25             str +="-";
26         }
27         System.out.println(str+name);
28         
29         for(Company component:children){
30             component.display(depth+2);//递归显示
31         }
32     }
33     
34     
35     //履行职责
36     @Override
37     public void lineOfDuty() {
38         // TODO Auto-generated method stub
39         for(Company component:children){
40             component.lineOfDuty();
41         }
42     }
43 
44 }

 

 

 1 //人力资源部
 2 public class HRDepartment extends Company {
 3 
 4     public HRDepartment(String name) {
 5         super(name);
 6     }
 7 
 8     @Override
 9     public void add(Company c) {
10     }
11 
12     @Override
13     public void remove(Company c) {
14     }
15 
16     @Override
17     public void display(int depth) {
18         String str = "";// 用于拼接'-',dept等于多少就表示拼接几个'-',用于显示效果
19         for (int i = 0; i < depth; i++) {
20             str += "-";
21         }
22         System.out.println(str + name);
23     }
24 
25     // 履行职责
26     @Override
27     public void lineOfDuty() {
28         System.out.println(name + "员工招聘管理培训");
29     }
30 }

 

 

 1 //财务部
 2 public class FinanceDepartment extends Company {
 3 
 4     public FinanceDepartment(String name) {
 5         super(name);
 6     }
 7 
 8     @Override
 9     public void add(Company c) {
10     }
11 
12     @Override
13     public void remove(Company c) {
14     }
15 
16     @Override
17     public void display(int depth) {
18         String str = "";//用于拼接'-',dept等于多少就表示拼接几个'-',用于显示效果
19         for(int i=0;i<depth;i++){
20             str +="-";
21         }
22         System.out.println(str+name);
23     }
24 
25     @Override
26     public void lineOfDuty() {
27         System.out.println(name+"公司财务收支管理");
28     }
29 
30 }

 

 1 //客户端
 2 public class TestClient {
 3     public static void main(String[] args) {
 4         ConcreteCompany root = new ConcreteCompany("北京总公司");
 5         root.add(new HRDepartment("总公司人力资源部"));
 6         root.add(new FinanceDepartment("总公司财务部"));
 7         
 8         ConcreteCompany comp = new ConcreteCompany("华东分公司");
 9         comp.add(new HRDepartment("华东分公司人力资源部"));
10         comp.add(new FinanceDepartment("华东分公司财务部"));
11         root.add(comp);//将子公司添加到总公司
12         
13         ConcreteCompany comp1 = new ConcreteCompany("南京办事处");
14         comp1.add(new HRDepartment("南京事处人力资源部"));
15         comp1.add(new FinanceDepartment("南京办事处财务部"));
16         root.add(comp1);//将子公司添加到总公司
17         
18         ConcreteCompany comp2 = new ConcreteCompany("杭州办事处");
19         comp2.add(new HRDepartment("杭州办事处人力资源部"));
20         comp2.add(new FinanceDepartment("杭州办事处财务部"));
21         root.add(comp2);//将子公司添加到总公司
22         
23         System.out.println("结构图:");
24         root.display(1);
25         
26         System.out.println("职责:");
27         root.lineOfDuty();
28         
29     }
30 }

打印结果:

结构图:
-北京总公司
---总公司人力资源部
---总公司财务部
---华东分公司
-----华东分公司人力资源部
-----华东分公司财务部
---南京办事处
-----南京事处人力资源部
-----南京办事处财务部
---杭州办事处
-----杭州办事处人力资源部
-----杭州办事处财务部
职责:
总公司人力资源部员工招聘管理培训
总公司财务部公司财务收支管理
华东分公司人力资源部员工招聘管理培训
华东分公司财务部公司财务收支管理
南京事处人力资源部员工招聘管理培训
南京办事处财务部公司财务收支管理
杭州办事处人力资源部员工招聘管理培训
杭州办事处财务部公司财务收支管理

 

UML图:

  

 

posted @ 2018-08-23 10:56  以前、以后  阅读(428)  评论(0编辑  收藏  举报