目录
组合模式,又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
【Mary今天过生日。“我过生日,你要送我一件礼物。”“嗯,好吧,去商店,你自己挑。”“这件 T 恤挺漂亮,买,这条裙子好看,买,这个包也不错,买。”“喂,买了三件了呀,我只答应送一件礼物的哦。”“什么呀,T 恤加裙子加包包,正好配成一套呀,小姐,麻烦你包起来。”“……”,MM都会用Composite模式了,你会了没有?
合成模式:合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。】
意图:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
关键代码:树枝内部组合该接口,并且含有内部属性List,里面放Component。
(1)优点:
(1)高层模块调用简单。
(2)节点自由增加。
(2)缺点:
在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
(3)使用场景:
部分、整体场景,如树形菜单,文件、文件夹的管理。
(4)注意事项:
定义时为具体类。
(5)应用实例
1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作数也可以是操作数、操作符和另一个操作数。
2、在JAVA AWT和SWING中,对于Button和Checkbox是树叶,Container是树枝。
代码
/** * 组合模式 */ //节点 abstract class Node { abstract public void p(); } //叶子节点 class LeafNode extends Node { String content; public LeafNode(String content) {this.content = content;} @Override public void p() { System.out.println(content); } } //支叶节点 class BranchNode extends Node { List<Node> nodes = new ArrayList<>(); String name; public BranchNode(String name) {this.name = name;} @Override public void p() { System.out.println(name); } public void add(Node n) { nodes.add(n); } } public class Main { public static void main(String[] args) { BranchNode root = new BranchNode("root"); BranchNode chapter1 = new BranchNode("chapter1"); BranchNode chapter2 = new BranchNode("chapter2"); Node r1 = new LeafNode("r1"); Node c11 = new LeafNode("c11"); Node c12 = new LeafNode("c12"); BranchNode b21 = new BranchNode("section21"); Node c211 = new LeafNode("c211"); Node c212 = new LeafNode("c212"); root.add(chapter1); root.add(chapter2); root.add(r1); chapter1.add(c11); chapter1.add(c12); chapter2.add(b21); b21.add(c211); b21.add(c212); tree(root, 0); } //递归函数遍历 static void tree(Node b, int depth) { for(int i=0; i<depth; i++) { System.out.print("--"); } b.p(); if(b instanceof BranchNode) { //强制转化 for (Node n : ((BranchNode)b).nodes) { tree(n, depth + 1); } } } }