内容简介:它属于
目的
它属于 structural 设计模式目录。 将对象组合成树结构以表示部分整体层次结构。Composite允许客户端统一处理单个对象和对象组合。
解释
现实世界的例子
每个句子都由单词组成,而单词又由字符组成。这些对象中的每一个都是可打印的,并且它们可以在它们之前或之后打印一些东西,例如句子总是以句号结束并且字总是在它之前有空格。
简单来说
复合模式允许客户以统一的方式处理单个对象。
维基百科说
在软件工程中,复合模式是一种分区设计模式。复合模式描述一组对象将以与单个对象实例相同的方式进行处理。组合的目的是将对象“组合”到树结构中,以表示 部分— 整体 层次结构。通过实现复合模式,客户可以统一处理单个对象和组合。
结构
参与者
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>
适用性
使用复合模式时
- 您想要表示对象的 部分— 整体 层次结构
- 您希望客户能够忽略对象组合和单个对象之间的差异。客户端将统一处理复合结构中的所有对象
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Java中的复合视图设计模式(Composite View Design Pattern)
- MongoDB指南---10、索引、复合索引 简介
- 为什么要有复合索引?
- python – Django或类似的复合主键
- GO的第五天,复合数据类型---数组、Slice
- Redis进阶应用:Redis+Lua脚本实现复合操作
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据挖掘导论
Pang-Ning Tan, Michael Steinbach / 范明 范宏建 / 人民邮电出版社 / 2006-01-01 / 49.00元
本书全面介绍了数据挖掘的理论和方法,旨在为读者提供将数据挖掘应用于实际问题所必需的知识。本书涵盖五个主题:数据、分类、关联分析、聚类和异常检测。除异常检测外,每个主题都包含两章:前面一章讲述基本概念、代表性算法和评估技术,后面一章较深入地讨论高级概念和算法。目的是使读者在透彻地理解数据挖掘基础的同时,还能了解更多重要的高级主题。此外,书中还提供了大量示例、图表和习题。 本书适合作为......一起来看看 《数据挖掘导论》 这本书的介绍吧!