Java设计模式(六)
------------组合模式
引子
如果你正在为一个大公司服务,我保证你自己都有可能至今还搞不清楚你们公司庞大的组织结构,小的部门可能有几个人,大的部门有几十人,还有的部门下面还有子部门,子子部门…(听起来都烦了,其实也不关心),如果有一天我们要做一个OA系统来描述这样一个组织结构了,他们许多的需求都是逐级下发的,那么我们面对一个如此复杂的结构应该如何应对呢?也许你就应该考虑一下组合模式了。
定义
组合模式------基本思想就是将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
实现
角色
我们在这还是对应公司组织结构的例子,来分析组合模式中的各个角色。
Component
抽象构件角色(Component):它为组合中的对象声明接口,也可以为共有接口实现缺省
行为。
/** * 公司抽象结构 可能包括人和部门 * @author Administrator * */ public abstract class AbstractStructure { public String name;
public AbstractStructure(String name){ this.name=name; } //抽象通用方法 public abstract void receiveEmail(); //组合模式通用方法 public abstract void addChildren(AbstractStructure a); public abstract void removeChildren(AbstractStructure a); public abstract Iterator getChildren(); public String getName() { return name; } }
|
Composite
树枝构件角色(Composite):在组合中表示分支节点对象——有子节点,实现抽象构件
角色声明的接口;存储子部件。在例子中对应的是部门。
public class Department extends AbstractStructure { public Department(String name) { super(name); } private List<AbstractStructure> staffs = new ArrayList<AbstractStructure>();
@Override public void addChildren(AbstractStructure a) { // TODO Auto-generated method stub staffs.add(a); } @Override public Iterator<AbstractStructure> getChildren() { // TODO Auto-generated method stub return staffs.iterator(); } @Override public void receiveEmail() { // TODO Auto-generated method stub Iterator<AbstractStructure> iter = this.getChildren(); while (iter.hasNext()) { AbstractStructure a = iter.next(); a.receiveEmail(); //System.out.println(a.getName() + "收到了部门群发Email"); } } @Override public void removeChildren(AbstractStructure a) { // TODO Auto-generated method stub staffs.remove(a); } } |
Leaf
树叶构件角色(Leaf):在组合中表示叶节点对象——没有子节点,实现抽象构件角色声
明的接口。在例子中对应的是职员。
public class Staff extends AbstractStructure { public Staff(String name) { super(name); } @Override public void addChildren(AbstractStructure a) { // TODO Auto-generated method stub System.out.println("不能对人员进行添加操作"); } @Override public Iterator getChildren() { // TODO Auto-generated method stub System.out.println("职员不能进行该查询"); return null; } @Override public void receiveEmail() { // TODO Auto-generated method stub System.out.println(this.name + "收到一封Emal"); } @Override public void removeChildren(AbstractStructure a) { // TODO Auto-generated method stub System.out.println("不能对人员进行删除操作"); } } |
客户端调用
public class MyTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub AbstractStructure root = new Department("神州集团"); AbstractStructure dp1 = new Department("项目一部"); AbstractStructure dp2 = new Department("项目二部"); AbstractStructure s1 = new Staff("张三"); AbstractStructure s2 = new Staff("李四"); AbstractStructure s3 = new Staff("王五"); AbstractStructure s4 = new Staff("刘二"); AbstractStructure s5 = new Staff("谢周三"); AbstractStructure s6 = new Staff("曼联");
root.addChildren(dp1); root.addChildren(dp2); dp1.addChildren(s1); dp1.addChildren(s3); dp1.addChildren(s2); dp1.addChildren(s4); dp2.addChildren(s5); dp2.addChildren(s6);
root.receiveEmail(); // dp1.receiveEmail(); // s5.receiveEmail(); } }
打印结果: 张三收到一封Email 王五收到一封Email 李四收到一封Email 刘二收到一封Email 谢周三收到一封Email 曼联收到一封Email |
总结
组合模式是一个应用非常广泛的设计模式,在许多其他的设计模式中都是用到了组合模式。它本身比较简单但是很有内涵,掌握了它对你的开发设计有很大的帮助。
模式优点
1. 使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2. 更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。
注意事项
1.Composite模式中,是将“Add***和Remove***方法和对象容器相关的方法”定义在“表示抽象对象的Component类”中,还是将其定义在“表示对象容器的Composite类”中,是一个关乎“透明性”和“安全性”的两难问题,需要仔细权衡结构,这又是必须付出的代价。
2.Composite模式在具体实现中,可以让父对象中的子对象反向追溯:如果父对象有频繁的遍历需求,可使用缓存技巧来改善效率