复合设计模式(Composite Design Pattern)

栏目: 后端 · 发布时间: 4年前

内容简介:它属于

目的

它属于 structural  设计模式目录。 将对象组合成树结构以表示部分整体层次结构。Composite允许客户端统一处理单个对象和对象组合。

解释

现实世界的例子

每个句子都由单词组成,而单词又由字符组成。这些对象中的每一个都是可打印的,并且它们可以在它们之前或之后打印一些东西,例如句子总是以句号结束并且字总是在它之前有空格。

简单来说

复合模式允许客户以统一的方式处理单个对象。

维基百科说

在软件工程中,复合模式是一种分区设计模式。复合模式描述一组对象将以与单个对象实例相同的方式进行处理。组合的目的是将对象“组合”到树结构中,以表示 部分— 整体 层次结构。通过实现复合模式,客户可以统一处理单个对象和组合。

结构

复合设计模式(Composite Design Pattern)

参与者

1.组件Component

  • 声明组合中对象的接口。
  • 根据需要,为所有类共有的接口实现默认行为。
  • 声明用于访问和管理其子组件的接口。
  • (可选)在递归结构中定义用于访问组件父级的接口,并在适当的情况下实现它。。

2.叶子 Leaf

  • 表示组合中的叶子对象。叶子没有子类。
  • 定义合成中基本对象的行为。

3.组合Composite

  • 定义具有子项的组件的行为。
  • 存储子组件。
  • 在Component接口中实现与子相关的操作。

4.客户端Client

  • 通过Component 接口操作组合中的对象  。

合作

  • 客户端使用Component类接口与组合结构中的对象进行交互。如果收件人是Leaf,则直接处理请求。如果收件人是Composite,则它通常将请求转发给其子组件,可能在转发之前和/或之后执行其他操作。 

源代码(示例1)

以我们上面的句子为例。这里有基类和不同的可打印类型

<b>public</b> <b>abstract</b> <b>class</b> LetterComposite {
  <b>private</b> List<LetterComposite> children = <b>new</b> ArrayList<>();
  <b>public</b> <b>void</b> add(LetterComposite letter) {
    children.add(letter);
  }
  <b>public</b> <b>int</b> count() {
    <b>return</b> children.size();
  }
  <b>protected</b> <b>void</b> printThisBefore() {}
  <b>protected</b> <b>void</b> printThisAfter() {}
  <b>public</b> <b>void</b> print() {
    printThisBefore();
    <b>for</b> (LetterComposite letter : children) {
      letter.print();
    }
    printThisAfter();
  }
}

<b>public</b> <b>class</b> Letter <b>extends</b> LetterComposite {
  <b>private</b> <b>char</b> c;
  <b>public</b> Letter(<b>char</b> c) {
    <b>this</b>.c = c;
  }
  @Override
  <b>protected</b> <b>void</b> printThisBefore() {
    System.out.print(c);
  }
}

<b>public</b> <b>class</b> Word <b>extends</b> LetterComposite {
  <b>public</b> Word(List<Letter> letters) {
    <b>for</b> (Letter l : letters) {
      <b>this</b>.add(l);
    }
  }
  @Override
  <b>protected</b> <b>void</b> printThisBefore() {
    System.out.print(<font>" "</font><font>);
  }
}

<b>public</b> <b>class</b> Sentence <b>extends</b> LetterComposite {
  <b>public</b> Sentence(List<Word> words) {
    <b>for</b> (Word w : words) {
      <b>this</b>.add(w);
    }
  }
  @Override
  <b>protected</b> <b>void</b> printThisAfter() {
    System.out.print(</font><font>"."</font><font>);
  }
}
</font>

然后我们有一个信使来传递信息

<b>public</b> <b>class</b> Messenger {
  LetterComposite messageFromOrcs() {
    List<Word> words = <b>new</b> ArrayList<>();
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('W'), <b>new</b> Letter('h'), <b>new</b> Letter('e'), <b>new</b> Letter('r'), <b>new</b> Letter('e'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('t'), <b>new</b> Letter('h'), <b>new</b> Letter('e'), <b>new</b> Letter('r'), <b>new</b> Letter('e'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('i'), <b>new</b> Letter('s'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('a'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('w'), <b>new</b> Letter('h'), <b>new</b> Letter('i'), <b>new</b> Letter('p'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('t'), <b>new</b> Letter('h'), <b>new</b> Letter('e'), <b>new</b> Letter('r'), <b>new</b> Letter('e'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('i'), <b>new</b> Letter('s'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('a'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('w'), <b>new</b> Letter('a'), <b>new</b> Letter('y'))));
    <b>return</b> <b>new</b> Sentence(words);
  }

  LetterComposite messageFromElves() {
    List<Word> words = <b>new</b> ArrayList<>();
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('M'), <b>new</b> Letter('u'), <b>new</b> Letter('c'), <b>new</b> Letter('h'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('w'), <b>new</b> Letter('i'), <b>new</b> Letter('n'), <b>new</b> Letter('d'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('p'), <b>new</b> Letter('o'), <b>new</b> Letter('u'), <b>new</b> Letter('r'), <b>new</b> Letter('s'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('f'), <b>new</b> Letter('r'), <b>new</b> Letter('o'), <b>new</b> Letter('m'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('y'), <b>new</b> Letter('o'), <b>new</b> Letter('u'), <b>new</b> Letter('r'))));
    words.add(<b>new</b> Word(Arrays.asList(<b>new</b> Letter('m'), <b>new</b> Letter('o'), <b>new</b> Letter('u'), <b>new</b> Letter('t'), <b>new</b> Letter('h'))));
    <b>return</b> <b>new</b> Sentence(words);
  }
}

然后它可以用作

LetterComposite orcMessage = <b>new</b> Messenger().messageFromOrcs();
orcMessage.print(); <font><i>// Where there is a whip there is a way.</i></font><font>
LetterComposite elfMessage = <b>new</b> Messenger().messageFromElves();
elfMessage.print(); </font><font><i>// Much wind pours from your mouth.</i></font><font>
</font>

源代码(例2)

步骤1:  创建 将被视为组件 Component 的   Employee 接口  。

/ <b>this</b> is the Employee <b>interface</b> i.e. Component.  
<b>public</b> <b>interface</b> Employee {  
    <b>public</b>  <b>int</b> getId();  
    <b>public</b> String getName();  
    <b>public</b> <b>double</b> getSalary();  
       <b>public</b> <b>void</b> print();  
    <b>public</b> <b>void</b> add(Employee employee);  
       <b>public</b> <b>void</b> remove(Employee employee);  
       <b>public</b> Employee getChild(<b>int</b> i);  
}<font><i>// End of the Employee interface. </i></font><font>
</font>

第2步:  创建一个 将被视为 Composite 的   BankManager 类,   并实现Employee接口。

<font><i>// this is the BankManager class i.e. Composite.  </i></font><font>
<b>import</b> java.util.ArrayList;  
<b>import</b> java.util.Iterator;  
<b>import</b> java.util.List;  
<b>public</b> <b>class</b> BankManager implements Employee {  
     <b>private</b> <b>int</b> id;  
     <b>private</b> String name;  
     <b>private</b> <b>double</b> salary;  
  
     <b>public</b> BankManager(<b>int</b> id,String name,<b>double</b> salary) {  
      <b>this</b>.id=id;      
      <b>this</b>.name = name;  
      <b>this</b>.salary = salary;  
     }  
         List<Employee> employees = <b>new</b> ArrayList<Employee>();  
     @Override  
     <b>public</b> <b>void</b> add(Employee employee) {  
        employees.add(employee);  
     }  
        @Override  
     <b>public</b> Employee getChild(<b>int</b> i) {  
      <b>return</b> employees.get(i);  
     }  
     @Override  
     <b>public</b> <b>void</b> remove(Employee employee) {  
      employees.remove(employee);  
     }    
     @Override  
     <b>public</b> <b>int</b> getId()  {  
      <b>return</b> id;  
     }  
     @Override  
     <b>public</b> String getName() {  
      <b>return</b> name;  
     }  
    @Override  
     <b>public</b> <b>double</b> getSalary() {  
      <b>return</b> salary;  
     }  
     @Override  
     <b>public</b> <b>void</b> print() {  
      System.out.println(</font><font>"=========================="</font><font>);  
      System.out.println(</font><font>"Id ="</font><font>+getId());  
      System.out.println(</font><font>"Name ="</font><font>+getName());  
      System.out.println(</font><font>"Salary ="</font><font>+getSalary());  
      System.out.println(</font><font>"=========================="</font><font>);  
        
      Iterator<Employee> it = employees.iterator();  
        
          <b>while</b>(it.hasNext())  {  
            Employee employee = it.next();  
            employee.print();  
         }  
     }  
}</font><font><i>// End of the BankManager class.  </i></font><font>
</font>

第3步:  创建一个 将被视为叶子 leaf 的   Cashier  类,   它将实现到Employee接口。

<b>public</b>  <b>class</b> Cashier implements Employee{  
    <font><i>/* 
         In this class,there are many methods which are not applicable to cashier because 
         it is a leaf node. 
     */</i></font><font>  
        <b>private</b> <b>int</b> id;  
            <b>private</b> String name;  
        <b>private</b> <b>double</b> salary;  
        <b>public</b> Cashier(<b>int</b> id,String name,<b>double</b> salary)  {  
            <b>this</b>.id=id;  
            <b>this</b>.name = name;  
            <b>this</b>.salary = salary;  
        }  
        @Override  
        <b>public</b> <b>void</b> add(Employee employee) {  
            </font><font><i>//this is leaf node so this method is not applicable to this class.  </i></font><font>
        }  
        @Override  
        <b>public</b> Employee getChild(<b>int</b> i) {  
            </font><font><i>//this is leaf node so this method is not applicable to this class.  </i></font><font>
            <b>return</b> <b>null</b>;  
        }  
        @Override  
        <b>public</b> <b>int</b> getId() {  
            </font><font><i>// TODO Auto-generated method stub  </i></font><font>
            <b>return</b> id;  
        }  
        @Override  
        <b>public</b> String getName() {  
            <b>return</b> name;  
        }  
        @Override  
        <b>public</b> <b>double</b> getSalary() {  
            <b>return</b> salary;  
        }  
        @Override  
        <b>public</b> <b>void</b> print() {  
            System.out.println(</font><font>"=========================="</font><font>);  
            System.out.println(</font><font>"Id ="</font><font>+getId());  
            System.out.println(</font><font>"Name ="</font><font>+getName());  
            System.out.println(</font><font>"Salary ="</font><font>+getSalary());  
            System.out.println(</font><font>"=========================="</font><font>);  
        }  
        @Override  
        <b>public</b> <b>void</b> remove(Employee employee) {  
            </font><font><i>//this is leaf node so this method is not applicable to this class.  </i></font><font>
        }  
}  
</font>

第4步:  创建一个  Accountant  类,它也将被视为一个  leaf ,它将实现到Employee接口。

<b>public</b> <b>class</b> Accountant implements Employee{  
<font><i>/* 
    In this class,there are many methods which are not applicable to cashier because 
    it is a leaf node. 
*/</i></font><font>  
    <b>private</b> <b>int</b> id;  
    <b>private</b> String name;  
    <b>private</b> <b>double</b> salary;  
   <b>public</b> Accountant(<b>int</b> id,String name,<b>double</b> salary)  {  
       <b>this</b>.id=id;  
       <b>this</b>.name = name;  
       <b>this</b>.salary = salary;  
   }  
   @Override  
   <b>public</b> <b>void</b> add(Employee employee) {  
       </font><font><i>//this is leaf node so this method is not applicable to this class.  </i></font><font>
   }  
   @Override  
   <b>public</b> Employee getChild(<b>int</b> i) {  
       </font><font><i>//this is leaf node so this method is not applicable to this class.  </i></font><font>
       <b>return</b> <b>null</b>;  
   }  
   @Override  
    <b>public</b> <b>int</b> getId() {  
        </font><font><i>// TODO Auto-generated method stub  </i></font><font>
        <b>return</b> id;  
   }  
   @Override  
   <b>public</b> String getName() {  
       <b>return</b> name;  
   }  
   @Override  
   <b>public</b> <b>double</b> getSalary() {  
       <b>return</b> salary;  
   }  
   @Override  
   <b>public</b> <b>void</b> print() {  
       System.out.println(</font><font>"========================="</font><font>);  
       System.out.println(</font><font>"Id ="</font><font>+getId());  
       System.out.println(</font><font>"Name ="</font><font>+getName());  
       System.out.println(</font><font>"Salary ="</font><font>+getSalary());  
       System.out.println(</font><font>"========================="</font><font>);  
   }  
  @Override  
   <b>public</b> <b>void</b> remove(Employee employee) {  
       </font><font><i>//this is leaf node so this method is not applicable to this class.  </i></font><font>
   }  
}  
</font>

步骤5:  创建一个  CompositePatternDemo 类,该类也将被视为 客户端  Client  ,ii将使用Employee接口。

<b>public</b> <b>class</b> CompositePatternDemo {  
    <b>public</b> <b>static</b> <b>void</b> main(String args[]){  
         Employee emp1=<b>new</b> Cashier(101,<font>"Sohan Kumar"</font><font>, 20000.0);  
         Employee emp2=<b>new</b> Cashier(102,</font><font>"Mohan Kumar"</font><font>, 25000.0);  
         Employee emp3=<b>new</b> Accountant(103,</font><font>"Seema Mahiwal"</font><font>, 30000.0);   
         Employee manager1=<b>new</b> BankManager(100,</font><font>"Ashwani Rajput"</font><font>,100000.0);  
            
          manager1.add(emp1);  
          manager1.add(emp2);  
          manager1.add(emp3);  
          manager1.print();  
        }  
}  
</font>

适用性

使用复合模式时

  • 您想要表示对象的 部分— 整体 层次结构
  • 您希望客户能够忽略对象组合和单个对象之间的差异。客户端将统一处理复合结构中的所有对象

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

刘强东自述

刘强东自述

刘强东 / 中信出版集团 / 2016-6-1 / 49.00

京东 1998年,京东还只是中关村一个经营光磁生意的小柜台,月营业额仅有几万元,如今则已经成长为中国营收规模超大的互联网企业,2015年全年营收1813亿,总交易额达到4627亿元; 为解决电商“最后一公里”的痛点,创立并自建B2C物流模式; 经常被争议,却始终坚持“不挣快钱”,选择上市不是因为“缺钱”,只为让合作伙伴睡得着觉,为用户和社会创造价值,由此成就让整个华尔街一片京东红......一起来看看 《刘强东自述》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具