策略模式
模式故事
小明所在的公司是一个游戏公司,他们现在正在设计一款游戏叫做《英雄对决》。在英雄对决中,每个英雄有2个技能可以使用,2个技能分别对用的键位是Q,W。公司让小明尝试设计英雄。很快的,小明就提出了自己的设计。小明的思路是这样的:
所有的不同的英雄都可以抽象出一个父类:英雄类。所有的英雄都有两个技能,这两个技能可以写成抽象方法,让子类去继承实现。这样在调用的时候,使用多态不同的英雄调用相同的方法时就会有不同的行为。
并且,这小明还给出了自己的代码:
父类
首先是所有英雄的抽象父类Hero类,Hero类有只有两个抽象的方法Q(),和W()。
public abstract class Hero{
public void Q();
public void W();
}
子类
然后让子类去继承父类,然后实现父类的抽象方法。
public class SuperMan extends Hero{
public void Q(){
System.out.println("激光眼");
}
public void W(){
System.out.println("飞行");
}
}
子类超人的技能是使用激光眼和飞行,而其他的子类也可以根据自己的需要做出不同的实现。比如蜘蛛侠的技能就是吐丝和爬墙。
public class SpiderMan extends Hero{
public void Q(){
System.out.println("爬墙");
}
public void W(){
System.out.println("吐丝");
}
}
现在看来,这样的设计还算可以。子类通过重写,相同的方法有了不同的实现。
问题
但是问题还是出现了,有一天小明的老板告诉小明现在我们的游戏要出一个新的英雄,而他将要拥有激光眼和吐丝的技能。小明想,这不是超人和蜘蛛侠的技能吗?但是,以前的设计好像没有办法让写过的代码重用。还好的是代码量不多,所以小明就又把激光眼和吐丝的技能写了一遍。
由于游戏卖的很火,新的英雄越来越多。由于游戏策划偷懒,现在很多的英雄的技能之一就是“激光眼”,“飞行”,“爬墙”,“吐丝”中的其中一个。小明也只能简单的将自己的代码复制粘贴。
但是最后还是除了大问题。
老板告诉小明,“激光眼”这个技能太强大了,所有的英雄的激光眼技能都要修改。此时小明才发现,由于有了很多的英雄都用“激光眼”的技能,现在他将要给所有有“激光眼”技能的英雄都进行修改。最后小明只好加班了。
解决办法
后来,小明被调到另外的一个部门去开发新的游戏。由于之前的《英雄对决》确实很火,所以这次小明的公司对游戏的设计中还是保留英雄有两个技能分别是Q,W。
此时的小明决定吃一堑长一智,对英雄的设计进行了重新的规划。首先他让两个技能的方法抽象成接口。
方法抽象成接口
public interface Skill{
public void useSkill();
}
为这两个接口写一些不同的实现,比如激光眼、爬墙什么的。
public class JiGuangYan implements Skill{
public void useSkill(){
System.out.println("激光眼");
}
}
public class PaQiang implements Skill{
public void useSkill(){
System.out.println("爬墙");
}
}
然后,小明重新设计了英雄的父类。
public abstract class Hero{
private Skill QSkill;
private Skill WSkill;
public void Q(){
QSkill.useSkill();
}
public void W(){
WSkill.useSkill();
}
}
子类
子类继承父类的时候,现在就变得非常简单。
public class NewMan extends Hero{
public NewMan(){
this.QSkill = new PaQiang();
this.WSkill = new JiGuangYan();
}
}
现在,现在老板说,所有的爬墙技能都需要修改,那么,我们只需要修改爬墙技能的接口实现就可以了。