喵星之旅-沉睡的猫咪-组合模式
一、组合模式是什么
组合模式也称为整体-部分模式,它的宗旨是通过将单个对象和组合对象用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性,属于结构型模式。
最常见的就是树结构的实现,比如红黑树。
这个给我的感觉更像是一种分形的特点,从任何一点去看,貌似都是一样的,这里指的是他的方法、属性等。从部分可以看出整体的结构。
二、组合模式的实现
下面通过实例演示一个组合模式如果来做,就是一个多叉树的实现。
第一步:问题必须要数型结构。比如我们的目录。如果是区分叶子和树枝的,要求分别创建不同的实现类,如果不区分,那就一个类直接实现,不需要抽象组件。
这里我们考虑是一个可以无限扩展的数,所以不区分。
第二步:明确每个节点的功能:一般是存储哪些数据、如何显示数据、子节点的操作、也不排除出现父节点的操作,还有其他的一些常用功能,比如遍历。
这里选择数据结点不会随便变化,不像红黑树那样复杂,是数据一确定就基本不改变,只有删除和添加的功能。
最后确定属性:子节点(如果数据量确定,就挨个列出(比如二叉树),不确定就用列表)这里选择list。存值value。目录级别(红黑树中应该没有,这里结构基本没变化,只要数据添加就是那个级别,其他数据不会影响这个数据)。
方法:添加节点、删除节点、遍历、属性的对应getset方法、构造器。
第三步:针对特别的场景,添加、或者修改一些方法、属性。
三、代码示例
节点类
package structure.composite; import java.util.ArrayList; import java.util.List; /** * * @author bunny~~我是兔子我会喵,我叫喵星兔。 *直接new的节点不能作为根结点,也不能直接遍历。 *必须通过静态方法才能创建根结点。 *这个要求不是必须的,只是这里选择这样做。 */ public class Node { //子节点 private List<Node> children; //存储数据 private String value; //目录层级 private Integer level; public List<Node> getChildren() { return children; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public int getLevel() { return level; } private void setLevel(Integer level) { this.level = level; } //处理子节点层级 private void setChildrenLevel() { for (int i = 0; i < children.size(); i++) { Node n = children.get(i); n.setLevel(level + 1); n.setChildrenLevel(); } } //遍历 public void show() { if (level == null) { System.out.println("不是正常结点"); return; } String s = ""; for (int i = 0; i < level; i++) { s += " "; } System.out.println(s + (children.size() > 0 ? "+" : "") + value); for (int i = 0; i < children.size(); i++) { children.get(i).show(); } } //添加节点,需要考虑层级 public void addNode(Node node) { children.add(node); node.setLevel(level + 1); node.setChildrenLevel(); } //删除节点 public void remove(Node node) { children.remove(node); } public Node() { children = new ArrayList<Node>(); } public Node(String value) { super(); this.value = value; children = new ArrayList<Node>(); } public static Node newRoot() { Node node = new Node(); node.setLevel(0); return node; } public static Node newRoot(String value) { Node node = new Node(value); node.setLevel(0); return node; } }
测试类
package structure.composite; public class Test { public static void main(String[] args) { Node n1 = new Node("a"); Node n2 = new Node("as"); Node n3 = new Node("ad"); Node n4 = new Node("af"); Node n5 = new Node("ag"); Node n6 = new Node("ah"); Node r = Node.newRoot("root"); r.addNode(n6); r.addNode(n4); n4.addNode(n2); n2.addNode(n1); n4.addNode(n3); r.show(); } }
四、组合模式分类
组合模式的结构:
抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。
树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
如何分类:
这种设计模式具体还分成两类:透明的、安全的。
如果需要区分树枝和树叶,那么上面的例子需要变成2个不同的对象,分别对树枝和树叶采取不同的处理。然后上面抽象出统一的接口。
接口的内容决定是透明的还是安全的组合模式。
所谓安全的组合模式,是调用方法时不会出现未实现的情况,所以接口内容较少,当要使用具体类型特有的功能时,需要知道具体类型。透明的在接口中有所有的方法,但是可能时空实现。
ps:项目地址 svn://47.105.188.20/kitty/2%E3%80%81code/pattern 用户名密码:reader/reader
作者:喵星兔
出处:https://www.cnblogs.com/kittybunny/
喵星之旅:https://www.cnblogs.com/kittybunny/p/12148641.html
我的视频:https://space.bilibili.com/518581788
更多内容:不咬人的小兔子
本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
我是兔子,我会喵,我叫喵星兔~~