定义:
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
结构:(书中图,侵删)
一个Component接口:定义统一的方法
若干树枝(Composite)类(继承Component):可包含若干个叶子(Leaf)节点
若干树叶(Leaf)类:叶子节点
书中说到这个模式有两种方式:
透明方式:在Component接口中定义添加和移除子节点的方法,但是叶子节点不需要这两个方法。这样写可以保持客户端调用的一致性。
安全方式:不在Component接口中定义添加和移除子节点的方法,直接在叶子节点中定义,这样写省去了叶子节点中的无用代码,但是客户端需要添加判断。
实例:
书中举到一个例子说是,假如你在word修改字体的大小时,你修改一个字和一段文字操作都是相同的。用户不用对此有差别操作,程序也不用差别对待。
然后,就让我想到了游戏中的队伍系统,在某些游戏里是可以跟随的,队长操纵自己,整个队伍都会跟着一起行动,和队长一个人行动没有什么区别。
玩家操纵的目标接口(Component):
package designpattern.composite; public abstract class Target { private String name;// 名称 public abstract void add(Target target);// 增加节点 public abstract void remove(Target target);// 删除节点 public abstract void move();// 移动 public abstract void attack();// 攻击 public String getName() { return name; } public void setName(String name) { this.name = name; } }
玩家类(Leaf):
package designpattern.composite; public class Player extends Target { private String name; public Player(String name) { super(); this.name = name; } @Override public void move() { System.out.println("[" + name + "]正在移动"); } @Override public void attack() { System.out.println("[" + name + "]发动攻击"); } @Override public void add(Target target) { } @Override public void remove(Target target) { } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Player [name=" + name + "]"; } }
队伍类(Composite):
package designpattern.composite; import java.util.ArrayList; import java.util.List; public class Team extends Target { List<Target> team = new ArrayList<>(); @Override public void add(Target target) { team.add(target); System.out.println(target.getName() + "加入队伍"); } @Override public void remove(Target target) { team.remove(target); System.out.println(target.getName() + "离开队伍"); } @Override public void move() { System.out.println(teamMembers() + "组成的队伍正在移动"); } @Override public void attack() { System.out.println(teamMembers() + "组成的队伍发动攻击"); } private String teamMembers() { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("["); for (Target target : team) { stringBuffer.append(target.getName() + " "); } stringBuffer.append("]"); return stringBuffer.toString(); } }
客户端:
package designpattern.composite; public class Client { public static void main(String[] args) { Player captainAmerica = new Player("美国队长"); captainAmerica.move(); captainAmerica.attack(); System.out.println("----------复联成立----------"); Player ironMan = new Player("钢铁侠"); Player hulk = new Player("绿巨人"); Team team = new Team(); team.add(captainAmerica); team.add(ironMan); team.add(hulk); team.move(); team.attack(); System.out.println("----------发生矛盾--------"); team.remove(ironMan); team.move(); team.attack(); } }
结果输出:
[美国队长]正在移动 [美国队长]发动攻击 ----------复联成立---------- 美国队长加入队伍 钢铁侠加入队伍 绿巨人加入队伍 [美国队长 钢铁侠 绿巨人 ]组成的队伍正在移动 [美国队长 钢铁侠 绿巨人 ]组成的队伍发动攻击 ----------发生矛盾-------- 钢铁侠离开队伍 [美国队长 绿巨人 ]组成的队伍正在移动 [美国队长 绿巨人 ]组成的队伍发动攻击
总结:
这个模式用在两个事物存在一定的包含关系,但是他们的行为又是一致的,为了让客户可以方便统一的使用他们。
套用书中的话:组合模式让客户可以一致的使用组合结构和单个对象。