作者:Flyingis
按照常理,还是先阐述基本概念,Decorator Pattern可以用即时战略游戏中兵种的装甲强度来理解,举一个典型的例子,魔兽争霸(或冰峰王座等)中山丘是个非常厉害的角色了,经常能够一锤击毙敌人的英雄和士兵,因此被誉为英雄杀手。既然是英雄杀手,时常需要冲锋陷阵,在作战过程中自然会面临敌人的围攻,此时我们有多种方式来提升山丘的抗击打能力,一种是升级他的护甲,一种是通过魔法师给他施加增加防护的魔法,一种是等级到6时使用终极魔法来大幅度提高装甲的防护,还有一种就是使用无敌的魔法瓶,在规定时间内谁都拿他没辙,等等。虽然我不知道暴雪公司的工程师具体是如何实现这种功能设计的,但绝对不会是准备多个具有不同防御等级的山丘对象来供程序调用,如Shanqiu1、Shanqiu2……ShanqiuN,这样设计笨拙,代码繁多,如果游戏中其他兵种的装甲、攻击力的设计都是如此,那即使是天才团队也会天天在上帝面前祷告的。
Decorator Pattern在这种情况下就可以发挥作用了,在普通装甲升级时,使用普通的装甲升级的装饰器,在使用终极魔法时,使用终极魔法装甲升级的装饰器。
public
abstract
class
Soldier
{
String info = "Soldier's name:";
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String getInfo()
{
return info;
}
public abstract int armor();
}
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public
abstract
class
SoldierDecorator extends Soldier
{
public abstract String getInfo();
}
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public
class
NormalArmorUpdate
extends
SoldierDecorator
{
Soldier soldier;
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public NormalArmorUpdate(Soldier soldier)
{
this.soldier = soldier;
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String getInfo()
{
return soldier.getInfo() + "Shanqiu normal update!";
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public int armor()
{
return soldier.armor() + 1;
}
}
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public
class
MagicArmorUpdate
extends
SoldierDecorator
{
Soldier soldier;
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public MagicArmorUpdate(Soldier soldier)
{
this.soldier = soldier;
}
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String getInfo()
{
return soldier.getInfo() + "Shanqiu magic update!";
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public int armor()
{
return soldier.armor() + 5;
}
}
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public
class
Shanqiu extend Soldier
{
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public int armor()
{
// 初始装甲厚度
return 3;
}
}
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public
class
PlayingGame
{
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String args[])
{
Soldier soldier = new Shanqiu();
System.out.println("Initialized armor:" + soldier.armor());
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
// 普通装甲升级
soldier = new NormalArmorUpdate(soldier);
System.out.println("Initialized armor:" + soldier.armor());
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
// 使用终极魔法后装甲升级
soldier = new MagicArmorUpdate(soldier);
System.out.println("Initialized armor:" + soldier.armor());
}
}
这样就避免了建立多个Shanqiu类来描述他的不同状态,终极魔法时间过去后,还可以增加一个Decorator来减去相应的装甲厚度,给编程带来了方便。
Decorator Pattern设计的目的,是为了能够在运行时而不是编译期来动态改变对象的状态,使用组合的方式来增减Decorator,而不是去修改原有的代码来满足业务的需要,这样利于程序的扩展。当然,在Java中使用接口同样能够轻便的实现文中描述的业务需要,但哪种更好,哪种更优?
Java中的IO提供了大量Decorator Pattern设计的实例,在笔者很久的 一篇随笔中对此进行了简单介绍,建议还是看看JDK的帮助文档。
参考资料:《Head First Design Pattern》
按照常理,还是先阐述基本概念,Decorator Pattern可以用即时战略游戏中兵种的装甲强度来理解,举一个典型的例子,魔兽争霸(或冰峰王座等)中山丘是个非常厉害的角色了,经常能够一锤击毙敌人的英雄和士兵,因此被誉为英雄杀手。既然是英雄杀手,时常需要冲锋陷阵,在作战过程中自然会面临敌人的围攻,此时我们有多种方式来提升山丘的抗击打能力,一种是升级他的护甲,一种是通过魔法师给他施加增加防护的魔法,一种是等级到6时使用终极魔法来大幅度提高装甲的防护,还有一种就是使用无敌的魔法瓶,在规定时间内谁都拿他没辙,等等。虽然我不知道暴雪公司的工程师具体是如何实现这种功能设计的,但绝对不会是准备多个具有不同防御等级的山丘对象来供程序调用,如Shanqiu1、Shanqiu2……ShanqiuN,这样设计笨拙,代码繁多,如果游戏中其他兵种的装甲、攻击力的设计都是如此,那即使是天才团队也会天天在上帝面前祷告的。
Decorator Pattern在这种情况下就可以发挥作用了,在普通装甲升级时,使用普通的装甲升级的装饰器,在使用终极魔法时,使用终极魔法装甲升级的装饰器。
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
这样就避免了建立多个Shanqiu类来描述他的不同状态,终极魔法时间过去后,还可以增加一个Decorator来减去相应的装甲厚度,给编程带来了方便。
Decorator Pattern设计的目的,是为了能够在运行时而不是编译期来动态改变对象的状态,使用组合的方式来增减Decorator,而不是去修改原有的代码来满足业务的需要,这样利于程序的扩展。当然,在Java中使用接口同样能够轻便的实现文中描述的业务需要,但哪种更好,哪种更优?
Java中的IO提供了大量Decorator Pattern设计的实例,在笔者很久的 一篇随笔中对此进行了简单介绍,建议还是看看JDK的帮助文档。
参考资料:《Head First Design Pattern》