《大话设计模式第十九章》
0.《设计模式》摘录
-
问题:
在图形编辑器中操纵的图形对象包括:最基本的图形元素,例如直线、圆、…
组合图形元素由基本图形元素和其它组合图形元素复合而成
希望对组合和基本图形有一样的操控 -
解决
为组合对象和基本对象建立共同的超类,不必区别是组合对象还是基本对象
组合对象内部结构形成递归的引用(或者包含)关系 -
客户程序使用Component接口与组合对象和基本对象以相同的方式交互
基本对象将直接做出响应
组合对象则把收到的请求转发给内部的每个子部件
1.问题
公司系统是一个树状、多层的结构,总部、分公司、办事处都有相似的功能,但他们直接又是整体和部分的关系。如果将他们都有的功能进行复制有很多问题。
如下图,总部下面有分公司,还有小部门,小部门如同叶子,不能延展。而分公司还能延展出办事处和小部门。所以相当于总部、分公司、办事处都有管理小部门和延展出下级公司的功能,而小部门就没有这些功能。
问题的关键:想让整体和部分有一致性(相同的操作)
2.组合模式
2.1 定义
组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
2.2 结构图和代码
-
结构图
Component:部件,包含叶子和composite的默认功能。声明接口用于访问和管理component子部件。
composite:相当于树枝,可以添加子部分和叶子,实现Component中抽象的方法。
leaf:树叶,不能添加和增加子部分。
-
代码
Component:
abstract class Component { protected String name; public Component(String name) { this.name=name; } public abstract void Add(Component c); public abstract void Remove(Component c);//通常都用Add Remove方法来提供和移除树叶、树枝 public abstract void Display(Component c); }
Leaf:
class Leaf extends Component { public Leaf(String name) { this.name=name; } public void Add(Component c) { System.out.println("不能添加"); } public void Remove(Component c) { System.out.println("不能移除"); } public void Display(int dept) { System.out.println('-'*dept+name); } }
Composite :
class Composite extends Component { private List<Component>children=new List<Component>(); public Composite(String name) { this.name=name; } public void Add(Component c) { children.Add(c) } public void Remove(Component c) { children.Remove(c) } public void Display(int dept) { System.out.println('-'*dept+name); foreach (Component component in children) component.Display(depth + 1); } }
例子:
static void Main(string args*) { Composite root = new Composite("root"); //生成树根root.根上长出两 叶 LeafA 和 LeafB root.Add(new Leaf("Leaf A")); root.Add(new Leaf("Leaf B")); //根上长出分枝Composite X, 分枝上也有两叶LeafXA和 LeafXB Composite comp = new Composite("Composite X"); comp.Add(new Leaf("Leaf XA")) comp.Add (new Leaf("Leaf XB")) root.Add(comp); //在Composite X 上再长出分枝Composite XY,分枝上也有两叶LeafXYA和LeafXYB Composite comp2 = new Composite("Composite XY"); comp2.Add(new Leaf("Leaf XYA")); comp2.Add(new Leaf("Leaf XYB")); comp.Add(comp2); //根部又长出两叶LeafC和LeafD,可惜LeafD 没长牢,被风吹走了 root.Add(new Leaf("Leaf C")); Leaf leaf = new Leaf("Leaf D"); root.Add(leaf); root.Remove(leaf); root.Display(); } //结果显示 -root --Leaf A --Leaf B --Composite X ---Leaf XA ---Leaf XB ---Composite XY ----Leaf XY ----Leaf XYB ----Leaf C
3.优点
-
什么时候使用组合模式?
当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,从而统一地使用组合结构中的所有对象时,就应该考虑用组合模式了
-
优点:
-
组合模式可以定义基本对象(叶子)、组合对象(树枝和根)的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去
-
组合模式让客户可以一致地使用组合结构和单个对象,用户是不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而 写一些选择判断语句了。
-