定义:
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
结构:(书中图,侵删)
一个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();
}
}
结果输出:
[美国队长]正在移动
[美国队长]发动攻击
----------复联成立----------
美国队长加入队伍
钢铁侠加入队伍
绿巨人加入队伍
[美国队长 钢铁侠 绿巨人 ]组成的队伍正在移动
[美国队长 钢铁侠 绿巨人 ]组成的队伍发动攻击
----------发生矛盾--------
钢铁侠离开队伍
[美国队长 绿巨人 ]组成的队伍正在移动
[美国队长 绿巨人 ]组成的队伍发动攻击
总结:
这个模式用在两个事物存在一定的包含关系,但是他们的行为又是一致的,为了让客户可以方便统一的使用他们。
套用书中的话:组合模式让客户可以一致的使用组合结构和单个对象。