设计模式:组合模式(Composite)
2017-07-07 21:10
267 查看
将对象组合成属性结构以表示“部分-总体”的层次结构。组合使得用户和单个对象和组合对象的使用具有一致性。
组合模式设计的角色:
1. Component:是组合中的对象声明接口。在适当的情况下。实现全部类共同拥有接口的默认行为。声明一个接口用于訪问和管理Component.
2. Leaf:在组合中表示叶子节点对象。叶子节点没有子节点。
3. Composite:定义树枝节点行为。用来存储子部件。在Component接口中实现与子部件有关操作,如增加和删除等。
举个简单样例(树枝和叶子)
1 Component
2 Leaf(树叶)
3 Composite(树枝)
4 測试代码
输出结果:
上面測试代码部分构建树结构的代码着实不太好看,效率太低。
事实上。在真实应用中。
并非这样子手工地构建一棵复杂的树,应该是我们已经将整棵树的节点内容、逻辑关系都存储在数据库表中,开发者编程从数据库中的表中读取记录来构建整棵树。
透明模式 vs 安全模式
上面的代码属于透明模式,我们先看看安全模式是怎么实现的:
更改一下Component:
再更改下Leaf
被称为安全模式是由于Leaf不具有add和remove等方法,这些详细方法是被下置到Composite类中去详细实现了。
透明模式将add和remove等方法上升到抽象构建类Component中去了。那么此时Leaf类在详细实现时就必须将继承而来的add和remove等不可用、不合理的方法给凝视掉(@Deprecated),并抛出适当的异常,不提供给用户使用。至于是使用透明模式还是安全模式就仁者见仁智者见智咯。只是,在这一模式中,相对于安全性,我们比較强调透明性。
使用场景:
用于对象的部分-总体层次结构,如树形菜单、目录菜单、部门组织架构等。
对用户隐藏组合对象与单个对象的不同,使得用户统一地使用组合结构中的全部对象。
优缺点
长处:使client调用简单,client能够一直的使用组合结构或当中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了client代码。更easy在组合体内增加对象不见。client不必由于增加了新的对象不见而更改代码。这一点符合开闭原则的要求。对系统的二次开发和功能扩展非常有利。
缺点:组合模式不easy限制组合中的构件。
Jdk中的组合模式
java.util.Map#putAll(Map)
java.util.List#addAll(Collection)
java.util.Set#addAll(Collection)
反面教材
回忆起曾经写页面菜单的时候,从数据库中读取相似的树形结构,当时没有採用这样的组合模式,而是限定死树的最大深度(页面的菜单深度不超过3。实际上也没见到过超过3的),这样前端js代码在深度不超过3时没有问题,当超过3时,就须要又一次编写页面菜单的js代码了,这样的扩展性并不好。假设当时採用了这样的组合模式就会好非常多。
写页面菜单已经是6年前的事了,代码早已不详~近期用项目需求要写一棵树,单例模式的。
大伙来看看有什么不妥之处。
首先定义实体类Entry
定义树节点(这里的叶子节点能够看成son==null的TreeNode。而树枝节点son!=null)
定义单例树节点
測试代码(根-集群-主机-虚拟机的层次关系):
大伙比对组合模式来看看这段代码有什么欠妥之处,欢迎在下方留言探讨。
參考资料
1. 《23种设计模式》
2. 《细数JDK里的设计模式》
3. 《组合模式(Composite)的安全模式与透明模式》
组合模式设计的角色:
1. Component:是组合中的对象声明接口。在适当的情况下。实现全部类共同拥有接口的默认行为。声明一个接口用于訪问和管理Component.
2. Leaf:在组合中表示叶子节点对象。叶子节点没有子节点。
3. Composite:定义树枝节点行为。用来存储子部件。在Component接口中实现与子部件有关操作,如增加和删除等。
举个简单样例(树枝和叶子)
1 Component
public abstract class Component { protected String name; public Component(String name) { this.name = name; } protected abstract void add(Component component); protected abstract void remove(Component component); protected abstract void operation(int depth); protected abstract List<Component> getChildren(); }
2 Leaf(树叶)
public class Leaf extends Component { public Leaf(String name) { super(name); } @Deprecated public void add(Component component) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Deprecated public void remove(Component component) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override protected void operation(int depth){ String temp = ""; for(int i=0;i<depth;i++) { temp += " "; } System.out.println(temp+this.name); } @Deprecated protected List<Component> getChildren() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } }
3 Composite(树枝)
public class Composite extends Component { private LinkedList<Component> children; public Composite(String name) { super(name); this.children = new LinkedList<>(); } public void add(Component component) { this.children.add(component); } @Override public void remove(Component component) { this.children.remove(component); } @Override public LinkedList<Component> getChildren() { return children; } @Override protected void operation(int depth) { String temp = ""; for(int i=0;i<depth;i++) { temp += " "; } LinkedList<Component> children = this.getChildren(); System.out.println(temp+this.name); for (Component c : children) { c.operation(depth+1); } } }
4 測试代码
public class MainTest { public static void main(String[] args) { Composite root = new Composite("树根"); Composite branch01 = new Composite("树枝01"); Composite branch02 = new Composite("树枝02"); Composite branch03 = new Composite("树枝03"); Composite branch04 = new Composite("树枝04"); branch01.add(new Leaf("树叶01")); branch01.add(new Leaf("树叶02")); branch03.add(new Leaf("树叶03")); branch03.add(new Leaf("树叶04")); branch03.add(new Leaf("树叶05")); branch01.add(branch03); branch02.add(new Leaf("树叶06")); branch02.add(new Leaf("树叶07")); branch02.add(new Leaf("树叶08")); branch04.add(new Leaf("树叶09")); branch04.add(new Leaf("树叶10")); branch02.add(branch04); root.add(branch01); root.add(branch02); root.operation(0); } }
输出结果:
树根 树枝01 树叶01 树叶02 树枝03 树叶03 树叶04 树叶05 树枝02 树叶06 树叶07 树叶08 树枝04 树叶09 树叶10
上面測试代码部分构建树结构的代码着实不太好看,效率太低。
事实上。在真实应用中。
并非这样子手工地构建一棵复杂的树,应该是我们已经将整棵树的节点内容、逻辑关系都存储在数据库表中,开发者编程从数据库中的表中读取记录来构建整棵树。
透明模式 vs 安全模式
上面的代码属于透明模式,我们先看看安全模式是怎么实现的:
更改一下Component:
public abstract class Component { protected String name; public Component(String name) { this.name = name; } protected abstract void operation(int depth); }
再更改下Leaf
public class Leaf extends Component { public Leaf(String name) { super(name); } @Override protected void operation(int depth){ String temp = ""; for(int i=0;i<depth;i++) { temp += " "; } System.out.println(temp+this.name); } }
被称为安全模式是由于Leaf不具有add和remove等方法,这些详细方法是被下置到Composite类中去详细实现了。
透明模式将add和remove等方法上升到抽象构建类Component中去了。那么此时Leaf类在详细实现时就必须将继承而来的add和remove等不可用、不合理的方法给凝视掉(@Deprecated),并抛出适当的异常,不提供给用户使用。至于是使用透明模式还是安全模式就仁者见仁智者见智咯。只是,在这一模式中,相对于安全性,我们比較强调透明性。
使用场景:
用于对象的部分-总体层次结构,如树形菜单、目录菜单、部门组织架构等。
对用户隐藏组合对象与单个对象的不同,使得用户统一地使用组合结构中的全部对象。
优缺点
长处:使client调用简单,client能够一直的使用组合结构或当中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,这就简化了client代码。更easy在组合体内增加对象不见。client不必由于增加了新的对象不见而更改代码。这一点符合开闭原则的要求。对系统的二次开发和功能扩展非常有利。
缺点:组合模式不easy限制组合中的构件。
Jdk中的组合模式
java.util.Map#putAll(Map)
java.util.List#addAll(Collection)
java.util.Set#addAll(Collection)
反面教材
回忆起曾经写页面菜单的时候,从数据库中读取相似的树形结构,当时没有採用这样的组合模式,而是限定死树的最大深度(页面的菜单深度不超过3。实际上也没见到过超过3的),这样前端js代码在深度不超过3时没有问题,当超过3时,就须要又一次编写页面菜单的js代码了,这样的扩展性并不好。假设当时採用了这样的组合模式就会好非常多。
写页面菜单已经是6年前的事了,代码早已不详~近期用项目需求要写一棵树,单例模式的。
大伙来看看有什么不妥之处。
首先定义实体类Entry
public class Entry { private String name; //some other properties public Entry(String name) { super(); this.name = name; } //getter and setter略 }
定义树节点(这里的叶子节点能够看成son==null的TreeNode。而树枝节点son!=null)
public class TreeNode { private Entry entry; private List<TreeNode> son; //getter and setter略 }
定义单例树节点
public class Tree { private TreeNode tree; private Tree() { tree = new TreeNode(); tree.setEntry(null); tree.setSon(new ArrayList<TreeNode>()); } public static class SingletonTreeInner { public static final Tree INSTANCE = new Tree(); } public static Tree getInstance() { return SingletonTreeInner.INSTANCE; } public TreeNode getTree() { return tree; } }
測试代码(根-集群-主机-虚拟机的层次关系):
public static void insertData() { Tree root = Tree.getInstance(); List<TreeNode> rootList = root.getTree().getSon(); //add cluster into root node TreeNode cluster = new TreeNode(); Entry entry1 = new Entry("cluster1"); cluster.setEntry(entry1); cluster.setSon(null); rootList.add(cluster); //add host into cluster node TreeNode host = new TreeNode(); Entry entry2 = new Entry("host1"); host.setEntry(entry2); host.setSon(null); if(cluster.getSon() == null) { cluster.setSon(new ArrayList<TreeNode>()); } List clusterList = cluster.getSon(); clusterList.add(host); //add vm into host node TreeNode vm = new TreeNode(); Entry entry3 = new Entry("vm1"); vm.setEntry(entry3); vm.setSon(null); if(host.getSon() == null) { host.setSon(new ArrayList<TreeNode>()); } List hostList = host.getSon(); hostList.add(vm); }
大伙比对组合模式来看看这段代码有什么欠妥之处,欢迎在下方留言探讨。
參考资料
1. 《23种设计模式》
2. 《细数JDK里的设计模式》
3. 《组合模式(Composite)的安全模式与透明模式》
相关文章推荐
- 设计模式之Composite(组合)
- 结构模式——设计模式之Composite(组合)[转载自http://www.jdon.com/]
- 设计模式之Composite(组合)
- 设计模式--组合模式(composite)
- 设计模式笔记--结构型模式之三--组合模式 Composite
- 设计模式(10)-组合模式(Composite)
- 窥视设计模式之组合模式(composite)
- 设计模式中结构型模式(三)组合模式(Composite)
- 设计模式之Composite(组合)
- 窥视设计模式之组合模式(composite)
- 设计模式之Composite(组合)
- java设计模式之Composite(组合) (转)
- C#设计模式之组合(Composite)
- [PHP设计模式]Composite(组合)模式范例
- 设计模式之Composite组合设计模式
- 设计模式----Composite(组合)模式
- 设计模式袖珍版 连续转载之 - Composite(组合)
- 设计模式之Composite(组合)
- 设计模式学习之组合模式(Composite)
- 设计模式之Composite(组合)