大话设计模式—组合模式
2016-04-01 22:07
330 查看
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
大话设计模式中程杰老师给出的定义是,组合模式:将对象组合成树形结构以表示”部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式结构图:
首先,让我们通过过一个简单的实例来简单了解一下组合模式做基本的用法。实例演示了一个组织中员工的层次结构。
创建Employee类:
测试类:
运行结果:
使用场景:
需求中是体现部分与整体层次结构的时候,以及当我们希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时。简而言之,就是涉及到部分、整体场景时,如树形菜单,文件、文件夹的管理。
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
一般在工作中说起部分和总体我们想到最多的大概就是总公司和分公司了,如果我们需要做一套办公管理系统,并且总公司的人力资源部、财务部等的办公挂历功能在所有的分公司也都要有,我们该怎么实现?
功能实现:
抽象公司类或接口
具体公司类(树枝节点)
财务部和人力资源部(树叶节点)
测试方法
运行结果:
这样,通过组合模式我们就定义了包含人力资源部和财务部这些基本对象和分公司等组合对象的类层次结构。
基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断的递归下去,在客户代码中,任何用到基本对象的地方都可以使用组合对象了。组合模式让客户可以一致的使用组合结构和单个对象。
应用实例:
1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作树、操作符和另一个操作数。
2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。
优点:
1、高层模块调用简单。
2、节点自由增加。
缺点:
在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
大话设计模式中程杰老师给出的定义是,组合模式:将对象组合成树形结构以表示”部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式结构图:
首先,让我们通过过一个简单的实例来简单了解一下组合模式做基本的用法。实例演示了一个组织中员工的层次结构。
创建Employee类:
package com.exercise.composite; import java.util.ArrayList; import java.util.List; public class Employee { private String name; private String dept; private int salary; private List<Employee> subordinates;//部下 //constructor public Employee(String name, String dept, int salary, List<Employee> subordinates) { super(); this.name = name; this.dept = dept; this.salary = salary; this.subordinates = subordinates; subordinates = new ArrayList<Employee>(); } public Employee(String name, String dept, int salary) { super(); this.name = name; this.dept = dept; this.salary = salary; 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 + " ]"; } }
测试类:
package com.exercise.composite; /** * 使用Employee来创建和打印员工的层次结构 * @author lmb * */ public class CompositePatternDemo { 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("-------------------公司员工情况----------------------"); System.out.println(CEO); for (Employee headEmployee : CEO.getSubordinates()) { //打印CEO的直属一级部下 System.out.println(headEmployee); for (Employee employee : headEmployee.getSubordinates()) { //打印CEO的二级部下 System.out.println(employee); } } } }
运行结果:
使用场景:
需求中是体现部分与整体层次结构的时候,以及当我们希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时。简而言之,就是涉及到部分、整体场景时,如树形菜单,文件、文件夹的管理。
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
一般在工作中说起部分和总体我们想到最多的大概就是总公司和分公司了,如果我们需要做一套办公管理系统,并且总公司的人力资源部、财务部等的办公挂历功能在所有的分公司也都要有,我们该怎么实现?
功能实现:
抽象公司类或接口
package com.composite; public abstract class Company { protected String name; public Company(String name){ this.name = name; } public abstract void add(Company company);//add public abstract void remove(Company company);//remove public abstract void display(int depth);//display public abstract void lineofDuty();//line of duty }
具体公司类(树枝节点)
package com.composite; import java.util.ArrayList; import java.util.List; public class ConcreteCompany extends Company { private List<Company> childrenCompany = new ArrayList<Company>(); public ConcreteCompany(String name) { super(name); } @Override public void add(Company company) { childrenCompany.add(company); } @Override public void display(int depth) { System.out.println("第 " + depth + " 层的机构名为: " + name); for (Company c : childrenCompany) { c.display(depth + 1); } } @Override public void lineofDuty() { for (Company c : childrenCompany) { c.lineofDuty(); } } @Override public void remove(Company company) { childrenCompany.remove(company); } }
财务部和人力资源部(树叶节点)
package com.composite; public class HRDepartment extends Company { public HRDepartment(String name) { super(name); } @Override public void add(Company company) { } @Override public void display(int depth) { System.out.println("第 " + depth + " 层的机构名为: " + name); } @Override public void lineofDuty() { System.out.println(name + " 负责员工招聘管理培训"); } @Override public void remove(Company company) { } }
package com.composite; public class FinanceDepartment extends Company { public FinanceDepartment(String name) { super(name); } @Override public void add(Company company) { } @Override public void display(int depth) { System.out.println("第 " + depth + " 层的机构名为: " + name); } @Override public void lineofDuty() { System.out.println(name + " 负责公司财务收支管理"); } @Override public void remove(Company company) { } }
测试方法
package com.composite; public class CompositePatternDemo { public static void main(String[] args) { //一个总公司 ConcreteCompany root = new ConcreteCompany("北京总公司"); root.add(new HRDepartment("总公司人力资源部")); root.add(new FinanceDepartment("总公司财务部")); //三个子公司 ConcreteCompany com1 = new ConcreteCompany("广州分公司"); com1.add(new HRDepartment("广州分公司人力资源部")); com1.add(new FinanceDepartment("广州分公司财务部")); root.add(com1); ConcreteCompany com2 = new ConcreteCompany("杭州分公司"); com2.add(new HRDepartment("杭州分公司人力资源部")); com2.add(new FinanceDepartment("杭州分公司财务部")); root.add(com2); ConcreteCompany com3 = new ConcreteCompany("深圳分公司"); com3.add(new HRDepartment("深圳分公司人力资源部")); com3.add(new FinanceDepartment("深圳分公司财务部")); root.add(com3); System.out.println("-------公司结构图--------"); root.display(1); System.out.println("----------各部门职责----------"); root.lineofDuty(); } }
运行结果:
这样,通过组合模式我们就定义了包含人力资源部和财务部这些基本对象和分公司等组合对象的类层次结构。
基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断的递归下去,在客户代码中,任何用到基本对象的地方都可以使用组合对象了。组合模式让客户可以一致的使用组合结构和单个对象。
应用实例:
1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作树、操作符和另一个操作数。
2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。
优点:
1、高层模块调用简单。
2、节点自由增加。
缺点:
在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
相关文章推荐
- JavaSE学习笔记(2016.4.1)
- add Two Numbers
- 剑指offer-面试题24:二叉搜索树的后序遍历序列
- 软考信息系统监理师:2016年4月1日作业
- Linux Shell 学习笔记2:Shell变量
- CF 627A. XOR Equation 位运算
- 串比较
- 读取相关连接的物理地址
- 1005 买书金钱分配问题
- 几个关键字
- Play framework 2.5新建工程执行日志
- 缓存与组
- C++第二次实验
- Python常用的字符串处理函数
- SQL语句中的查询操作
- Could not connect to Redis No route to host问题解决
- 3月31:蘑菇街实习笔试:求桌子达最大平衡的代价
- RoundCornerTextview2
- windows编程显示客户区窗口分辨率
- 51 Nod 1215 数组的宽度(单调栈)