设计模式-09-组合模式
个人github地址:HibisciDai
设计模式系列项目源码:HibisciDai/DesignPattern-LearningNotes-HibisciDai
processon在线UML类图:processon
[TOC]
设计模式-09-组合模式 组合模式(Composite Pattern) 意图 将对象组合成树形结构以表示“部分-整体”的层次结构。 组合模式使得用户对单个对象和组合对象的使用具有一致性。
The Intent of this pattern is to compose objects into tree structures to represent partwhole hierachies.Composite lets clients treat individual objects and compositions of objects uniformly.
主要解决 模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用
表示对象的部分-整体层次结构(树形结构)。
用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
关键代码 树枝内部组合该接口,并且含有内部属性 List,里面放 Component。
如何解决 树枝和叶子实现统一接口,树枝内部组合该接口。
应用实例
算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作数、操作符和另一个操作数。
在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。
优点
缺点 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
使用场景 部分、整体场景,如树形菜单,文件、文件夹的管理。
注意事项 定义时为具体类。
案例1 文件和文件夹。
类图
代码 pattern09.composite.demo1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 public abstract class AbstractFile { protected String fname; public AbstractFile (String fname) { super (); this .fname = fname; } abstract void add (AbstractFile abstractFile) ; abstract void remove (AbstractFile abstractFile) ; abstract void printName () ; void operation () { System.out.println("文件其他操作..." ); } } public class File extends AbstractFile { public File (String fname) { super (fname); } @Override void add (AbstractFile abstractFile) { System.out.println("File" + "添加" ); } @Override void remove (AbstractFile abstractFile) { System.out.println("File" + "移除" ); } @Override void printName () { System.out.println("File" + fname); } } public class Folders extends AbstractFile { ArrayList<AbstractFile> afs = new ArrayList <AbstractFile>(); public Folders (String fname) { super (fname); } @Override void add (AbstractFile abstractFile) { afs.add(abstractFile); System.out.println("Folders" + "添加" ); } @Override void remove (AbstractFile abstractFile) { afs.remove(abstractFile); System.out.println("Folders" + "添加" ); } @Override void printName () { System.out.println("Folders" + fname); for (AbstractFile af : afs) { af.printName(); } } }
案例2 对于功能不太复杂的,可以简化类图,即合并为一个类。
我们有一个类 Employee,该类被当作组合模型类。CompositePatternDemo,我们的演示类使用 Employee 类来添加部门层次结构,并打印所有员工。
类图
代码 pattern09.composite.demo2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class Employee { private String name; private String dept; private int salary; private List<Employee> subordinates; public Employee (String name, String dept, int sal) { this .name = name; this .dept = dept; this .salary = sal; subordinates = new ArrayList <Employee>(); } public void add (Employee e) { subordinates.add(e); } public void remove (Employee e) { subordinates.remove(e); } public List<Employee> getSubordinates () { return subordinates; } public String toString () { return ("Employee :[ Name : " + name + ", dept : " + dept + ", salary :" + salary + " ]" ); } }
测试输出 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class Main { public static void main (String[] args) { Employee CEO = new Employee ("John" , "CEO" , 30000 ); Employee headSales = new Employee ("Robert" , "Head Sales" , 20000 ); Employee headMarketing = new Employee ("Michel" , "Head Marketing" , 20000 ); Employee clerk1 = new Employee ("Laura" , "Marketing" , 10000 ); Employee clerk2 = new Employee ("Bob" , "Marketing" , 10000 ); Employee salesExecutive1 = new Employee ("Richard" , "Sales" , 10000 ); Employee salesExecutive2 = new Employee ("Rob" , "Sales" , 10000 ); CEO.add(headSales); CEO.add(headMarketing); headSales.add(salesExecutive1); headSales.add(salesExecutive2); headMarketing.add(clerk1); headMarketing.add(clerk2); System.out.println(CEO); for (Employee headEmployee : CEO.getSubordinates()) { System.out.println(headEmployee); for (Employee employee : headEmployee.getSubordinates()) { System.out.println(employee); } } } }
1 2 3 4 5 6 7 Employee :[ Name : John, dept : CEO, salary :30000 ] Employee :[ Name : Robert, dept : Head Sales, salary :20000 ] Employee :[ Name : Richard, dept : Sales, salary :10000 ] Employee :[ Name : Rob, dept : Sales, salary :10000 ] Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ] Employee :[ Name : Laura, dept : Marketing, salary :10000 ] Employee :[ Name : Bob, dept : Marketing, salary :10000 ]