Java设计模式之从[魔兽世界副本]分析原型(Prototype)模式

来源:互联网 发布:淘宝翡翠手镯 编辑:程序博客网 时间:2024/06/10 02:28

  “副本”是网络游戏任务的一种形式,它最初出现于无尽的任务,现在运用得最有名的就是魔兽世界的副本了,我们将它称为副本任务。副本任务一般是一个队伍的人一起闯关的,假设有队伍A、队伍B、队伍C,分别对同一个副本任务发出挑战,他们在副本任务中的行为是不相干的。也就是说,A队伍在副本任务中消灭boss、开启宝箱,不会对B、C两支队伍造成任何影响,B、C同理。因此,“副本”可以理解成,从任务的原型中拷贝,然后给不同的队伍去执行。

  现在从“原型模式”来思考一下副本的实现(真正的魔兽世界是如何实现的我不知道)。原型模式的意图是从原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。以魔兽世界中的“死亡矿井”副本为例,它是一个最基本的副本,玩家达到10级就可以接受此副本任务。为了简化模型,我把副本任务的属性分为任务名、敌人数量和难度等级。若玩家进入了一个副本任务,游戏则先会寻找这个副本任务的原型(也就是一个对象),接下来把这个对象复制(clone)一次,再把复制好的对象返回给玩家,告诉玩家:你的副本任务我已经复制好了,由于是从原型中拷贝下来的,所以你在这个任务里怎么样都不会影响到别人。

  以下是Java代码:

interface Cloneable{    Object clone();}class Deadmines implements Cloneable {    String mapName = "死亡矿井";    int enemies ;    int difficulty ;    public Deadmines(int _difficulty, int _enemies){        difficulty = _difficulty;        enemies = _enemies;    }    public Object clone(){        return new Deadmines(difficulty, enemies);    }    public void print(){        System.out.printf("副本名: %s, 敌人数目: %d, 难度: %d\n", mapName, enemies, difficulty);     }}class Prototype{    public static void main(String[] args) {        Deadmines deadminesPrototype = new Deadmines(10, 200);        Deadmines playerDeadmines = (Deadmines)deadminesPrototype.clone();        playerDeadmines.print();        System.out.println(deadminesPrototype == playerDeadmines);    }}

输出结果:

副本名: 死亡矿井, 敌人数目: 200, 难度: 15
false

  稍微说明一下。main方法中的最后一行是用于判断原型和副本是否为同一引用,结果显然是false,因为副本是被拷贝出来的,并不是直接返回原型。通俗地来讲,原型模式就是以一个对象为模板,来构造与它一样的对象。它可以隐藏具体的克隆细节(如我们在使用时只需要调用clone方法,而不需要知道它是怎么clone的)。

  另外还要提到的是,在Java中本身就存在Cloneable接口,在上例中我们是自己重新定义了一个Cloneable。另外,Object类中本身也有一个受保护的方法clone,它可用于改写。在Java文档中写道,Object的clone方法没有继承Cloneable接口,如果直接调用,则会触发CloneNotSupportedException异常。能够调用clone方法的对象一定要继承Cloneable接口。(CloneNotSupportedException - if the object's class does not support the Cloneable interface. Subclasses that override the clone method can also throw this exception to indicate that an instance cannot be cloned.)

  总结一下,当一个系统应该独立于它产品创建、构成时、实例化的对象是运行时加载(如副本任务)时、为了避免创建一个与产品类层次平行的工厂类层次时、当一个类的实例只能有几个不同状态组合中的一种时,可以考虑使用原型模式。它在Java、C#中得到了广泛的应用。

1 0