RPG游戏中的包裹(或者称为背包)是玩家携带物品的地方,它的大小决定着玩家能够携带物品数量。如在魔兽世界中,玩家起初的物品栏(将物品栏视为玩家的唯一一个包裹)的格子很少,但是玩家可以将新的包裹放在物品栏中,达到扩充物品栏的效果。也就是说,物品栏可以放消耗品、武器等零散的物品,当然也可以放包裹。
假定魔兽世界有如下设定:玩家一开始拥有一个默认的包裹(物品栏),玩家可以获得新的包裹放在物品栏上。包裹可以存放武器、防具、消耗品,以及包裹。它可以无限次的迭代,形成树状,如下所示:
以上的模型反应了组合(Composite)模式的思维。在上述的树中,我们把节点分为两种:部分和整体。所谓“部分”,就是指那些没有子节点的项,如炉石、匕首等;整体是指拥有子节点的项,它可以储存子节点。组合模式的意图是将对象组成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
下面是实现这个机制的Java代码:
import java.util.ArrayList;
interface WowItem {
String getName();
void add(WowItem item);
void remove(WowItem item);
WowItem get(int i);
void print();
}
class Bag implements WowItem {
ArrayList<WowItem> items = new ArrayList<WowItem>();
public String getName(){
return "背包 ";
}
public void add(WowItem item){
items.add(item);
}
public void remove(WowItem item){
items.remove(item);
}
public WowItem get(int i){
return items.get(i);
}
public void print(){
System.out.println(getName() + "{" );
for ( WowItem i : items){
i.print();
}
System.out.println("}");
}
}
class Hearthstone implements WowItem {
public String getName(){
return "炉石";
}
public void add(WowItem item){ }
public void remove(WowItem item){ }
public WowItem get(int i){ return null; }
public void print(){
System.out.println(getName());
}
}
class Dagger implements WowItem {
public String getName(){
return "匕首";
}
public void add(WowItem item){ }
public void remove(WowItem item){ }
public WowItem get(int i){ return null; }
public void print(){
System.out.println(getName());
}
}
class Composite
{
public static void main(String[] args) {
WowItem myBag = new Bag();
WowItem smallBag = new Bag();
myBag.add(new Dagger());
myBag.add(smallBag);
smallBag.add(new Dagger());
myBag.add(new Hearthstone());
myBag.print();
}
}在main方法中,我们定义了个根节点myBag,为它增加了一把匕首Dagger、一个小背包(smallBag),在小背包中添加了一把匕首,然后再在myBag中添加了一个炉石,程序运行结果如下:
背包 {
匕首
背包 {
匕首
}
炉石
}
最后再说两个问题:
一、你可能会发现,对于非组合类(Dagger、Hearthstone),有许多代码是多余的,例如它们不需要实现add、remove、get等方法,如果这些类均继承于WowItem,代码编写会比较繁琐(因为要每个继承的方法都要空实现),而且会损失安全性——我们可能一不小心为一个Dagger调用了add方法或者remove方法。因此,你可以选择为这些非组合类建立一个另外一个类来管理这些子部件,这样的话,就丧失了透明性,它让部分和整体变成了两个独立的部分,我是不推荐这么做的。改善的方法有很多,例如非组合类都继承于一个抽象类A,而这个抽象类A是继承于WowItem的,并且实现了add、remove、get方法,均为抛出一个异常。那么,只要是非组合类调用了add、remove或get,均会得到一个异常。
二、组合在实际的使用中用途非常广。如在编写界面的时候,用到的控件机制——有些控件可以当做“容器”,例如,Frame中可以放入Button、RadioButton,也可以放入Frame,这就是典型的组合模式的运用。
Java设计模式之从[魔兽世界包裹系统]分析组合(Composite)模式,布布扣,bubuko.com
Java设计模式之从[魔兽世界包裹系统]分析组合(Composite)模式
原文:http://blog.csdn.net/froser/article/details/23206041