复合设计模式(Composite Design Pattern)

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

内容简介:它属于

目的

它属于 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>

适用性

使用复合模式时

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

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

查看所有标签

猜你喜欢:

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

Distributed Systems

Distributed Systems

Sukumar Ghosh / Chapman and Hall/CRC / 2014-7-14 / USD 119.95

Distributed Systems: An Algorithmic Approach, Second Edition provides a balanced and straightforward treatment of the underlying theory and practical applications of distributed computing. As in the p......一起来看看 《Distributed Systems》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换