组合模式
-
基本介绍
- 组合模式,又叫部分整体模式,他创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系。
- 组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
- 这种类型的设计模式属于结构型模式。
- 组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象。
- 在现实生活中,存在很多“部分和整体”的关系,例如,大学中的部门与学院、总公司中的部门与子公司、学习用品中的书和书包、生活用品中的衣服与衣柜以及厨房中的锅碗瓢盆等。在软件开发中,文件系统中的文件与文件夹、窗体程序中的简单控件与容器控件等。对这些简单对象与复合对象的处理,如果用组合模式来实现会很方便。
-
优点:
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象还是组合对象,这就简化了客户端代码。
- 更容易在组合体内加入新的对象,客户端不会因为加入新的对象而更改源代码,满足“开闭原则”。
-
缺点:
- 设计较复杂,客户端需要花更多的时间理清类之间的层次关系。
- 不容易限制容器中的构件。
-
解决的问题:
- 组合模式解决这样的问题,当我们要处理的对象可以生成一棵树形结构,而我们要对树上的节点和叶子进行操作时,它能够提供一致的方式,而不用考虑它是节点还是叶子。
- 对应的示意图
-
模式结构:
- 抽象构件Conponent角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口。在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件来完成。
- 树叶构件Leaf角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中声明的公共接口。
- 树枝构件Composite角色:是组合中的分支节点对象,它有子节点。它实现 抽象构件角色中声明额接口,它的主要作用是存储和管理子部件,通常包含Add()、Remove()、GetChild()等方法。
-
示例(透明式组合模式):
-
抽象构件:
-
//抽象构件 public interface Component { public void add(Component c); public void remove(Component c); public Component getChild(int i); public void operation(); }
-
树枝构件:
-
//树枝构件 public class Composite implements Component{ private ArrayList<Component> children=new ArrayList<Component>(); @Override public void add(Component c) { children.add(c); } @Override public void remove(Component c) { children.remove(c); } @Override public Component getChild(int i) { return children.get(i); } @Override public void operation() { for (Component com:children) { com.operation(); } } }
-
树叶构件:
-
public class Leaf implements Component { private String name; public Leaf(String name) { this.name = name; } @Override public void add(Component c) { } @Override public void remove(Component c) { } @Override public Component getChild(int i) { return null; } @Override public void operation() { System.out.println("树叶"+name); } }
-
客户端:
-
public class Client { public static void main(String[] args) { Component composite1 = new Composite(); Component composite2 = new Composite(); Component leaf1=new Leaf("1"); Component leaf2=new Leaf("2"); Component leaf3=new Leaf("3"); composite1.add(leaf1); composite1.add(composite2); composite2.add(leaf2); composite2.add(leaf3); composite1.operation(); } }
-
-
-
示例(安全式组合模式)
-
//抽象构件 public interface Component { public void operation(); } //树枝构件 public class Composite implements Component { private ArrayList<Component> children=new ArrayList<Component>(); @Override public void operation() { for (Component com:children) { com.operation(); } } public void add(Component c) { children.add(c); } public void remove(Component c) { children.remove(c); } public Component getChild(int i) { return children.get(i); } } //树叶构件 public class Leaf implements Component{ private String name; public Leaf(String name) { this.name = name; } @Override public void operation() { System.out.println("树叶"+name); } } public class Client { public static void main(String[] args) { Composite composite1 = new Composite(); Composite composite2 = new Composite(); Leaf leaf1=new Leaf("1"); Leaf leaf2=new Leaf("2"); Leaf leaf3=new Leaf("3"); composite1.add(leaf1); composite1.add(composite2); composite2.add(leaf2); composite2.add(leaf3); composite1.operation(); } }
-
透明式和安全式主要不同在于抽象构件是否声明了抽象的对构件的操作方法。
- 如果声明了,则树叶和树枝都需要实现。此时客户端不需要知道哪些是树叶,哪些是树枝。
- 如果没有声明,则树枝自己实现相应的方法。客户需要知道哪些是树叶,哪些是树枝。