在HTML5版“街头霸王”的第一版代码中,负责创建游戏人物的Spirit 类非常庞大,不仅要负责创建人物精灵,还包括了人物的攻击、防御等动作方法,代码如下:
var Spirit = function( name ){ this.name = name; }; Spirit.prototype.attack = function( type ){ // 攻击 if ( type === 'waveBoxing' ){ console.log( this.name + ': 使用波动拳' ); }else if( type === 'whirlKick' ){ console.log( this.name + ': 使用旋风腿' ); } }; var spirit = new Spirit( 'RYU' ); spirit.attack( 'waveBoxing' ); // 输出:RYU: 使用波动拳 spirit.attack( 'whirlKick' ); // 输出:RYU: 使用旋风腿
后来发现,Spirit.prototype.attack这个方法实现是太庞大了,实际上它完全有必要作为一个单独的类存在。面向对象设计鼓励将行为分布在合理数量的更小对象之中:
var Attack = function( spirit ){ this.spirit = spirit; }; Attack.prototype.start = function( type ){ return this.list[ type ].call( this ); }; Attack.prototype.list = { waveBoxing: function(){ console.log( this.spirit.name + ': 使用波动拳' ); }, whirlKick: function(){ console.log( this.spirit.name + ': 使用旋风腿' ); } };
现在的Spirit类变得精简了很多,不再包括各种各样的攻击方法,而是把攻击动作委托给Attack类的对象来执行,这段代码也是策略模式的运用之一:
var Spirit = function( name ){ this.name = name; this.attackObj = new Attack( this ); }; Spirit.prototype.attack = function( type ){ // 攻击 this.attackObj.start( type ); }; var spirit = new Spirit( 'RYU' ); spirit.attack( 'waveBoxing' ); // 输出:RYU: 使用波动拳 spirit.attack( 'whirlKick' ); // 输出:RYU: 使用旋风