zoukankan      html  css  js  c++  java
  • 组合模式--分公司=一部门

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

      为什么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图:

      

  • 相关阅读:
    抽象类的子类能够new
    Codeforces Round #250 (Div. 2) A
    软件架构设计箴言理解
    UVA1422-Processor(二分法+优先队列)
    猜你喜欢-----推荐系统原理介绍
    Android------Intent.createChooser
    mongodb3.0 性能測试报告 二
    *Android 多线程下载 仿下载助手(改进版)
    Gson解析数组和list容器
    oracle dbms_repcat_admin能带来什么安全隐患
  • 原文地址:https://www.cnblogs.com/lixianyuan-org/p/9522481.html
Copyright © 2011-2022 走看看