小帅刚毕业就进了一家游戏公司工作,公司正在开发一款新的即时战略游戏,领导让他设计游戏里的兵种及行为。 在第一个版本里,只有步兵,骑士和弓箭手三个兵种,每个兵种都有移动,停止,攻击和自愈四种行为。 小帅马上做了个简单的设计,每个兵种都能移动和停止,不同的兵种有不同的战斗方式和回血速度。 于是设计了Unit(兵种)抽象类,实现了move()和stop()方法,各个兵种继承该超类,然后根据自己的战斗特点实现超类的中的fight()和selfHealing()抽象方法。 子类重用的了父类的代码,又根据自己的特点实现了抽象方法,嗯,小帅觉得很满意,就在小组中做了。 “我觉得还应该加个投石车兵种,攻城利器”,小组成员提议。 “没问题,加个投石车的子类就行了”,小帅自信地说。 小帅立马想到了接口,把自愈方法单独抽离出来,放到一个自愈接口里,有自愈能力的兵种都继承该接口。没自愈能力的投石车,就不用继承了。 ”这样看上去好多了,但是代码不能复用,每个子类都要重新实现fight()和selfHealing()方法,以后我们要设计几十个兵种,每个兵种都得重新实现一遍,这样太麻烦了。”老王犀利得指出了问题所在。 小帅一时语塞。 老王看了看小帅一脸迷茫的样子,托了托眼镜,继续说道:“我们要找出应用中经常变化的部分,把它们独立出来,和那些不需要变动的代码区分开来,这是个重要的设计原则。” “在这个例子中,fight()和selfHealing()方法每个子类的实现都不一样,属于经常变化的部分,我们可以设计SelfHealingBeHavior和FightBeHavior接口,把战斗行为和自愈行为提取出来,这样就应用了一个设计原则:针对接口编程,而不是针对实现编程。” “这里我们可以使用策略(Strategy)模式进行设计”,老王已经停不下来了,继续说道: 这里的战斗行为和自愈行为就是“算法”,我们把算法封装起来,各种战斗和自愈的实现方式都在子类中实现,客户端只要调用接口就行了,不用管具体是怎么实现的。 应用了策略模式后的类图: 说了这么多,也该上代码了。 “setFightBeHavior(FightBeHavior fi)方法和setSelfHealingBeHavior(SelfHealingBeHavior se)方法,能在程序运行中动态的切换实现的算法,这是策略模式的一大优点。“,老王补充道。 小帅看着代码,陷入了沉思,真是越看越有味道。 “原来FightBeHavior接口就是兵器库(算法库),以后不管用到什么其他的战斗方式,只要在实现类里增加就行了,就像在兵器库(算法库)里增加兵器(算法),比如:双节棍,大刀,流星锤等等,如果有新的兵种直接拿来用就行了,实现了类的复用。 战斗方式可以随时替换,并且不会影响到具体兵种的使用。“小帅貌似明白了策略模式的精髓所在,显得有点兴奋。 老王点点头,开心的笑了,“就是这样啊,你已经学会策略模式了”。
继承很不错
”可是投石车明明不能自愈,却还要实现父类的selfHealing()方法,不觉得很奇怪吗?”项目组的老王立马指出了问题。
接口怎么样?
针对接口编程,而不是针对实现编程
策略(Strategy)模式的定义如下:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
FightBeHavior接口以及实现类
/** * 战斗接口 * @author zhanyd */ public interface FightBeHavior { /** * 战斗 */ void fight(); }
/** * 剑战斗子类 * @author zhanyd */ public class FightWithSword implements FightBeHavior{ public void fight() { System.out.println("攻击:看我的剑法"); } }
/** * 弓箭战斗子类 * @author zhanyd */ public class FightWithArrow implements FightBeHavior{ public void fight() { System.out.println("攻击:我射箭-->"); } }
/** * 长枪战斗子类 * @author zhanyd */ public class FightWithSpear implements FightBeHavior{ public void fight() { System.out.println("攻击:看我的长枪"); } }
/** * 石头战斗子类 * @author zhanyd */ public class FightWithStone implements FightBeHavior{ public void fight() { System.out.println("攻击:我扔石头"); } }
SelfHealingBeHavior接口以及实现类
/** * 自愈接口 * @author zhanyd */ public interface SelfHealingBeHavior { /** * 自愈 */ void selfHealing(); }
/** * 快速回血子类 * @author zhanyd */ public class SelfHealingFast implements SelfHealingBeHavior{ public void selfHealing() { System.out.println("我每秒回血3%n"); } }
/** * 中速回血子类 * @author zhanyd */ public class SelfHealingNormal implements SelfHealingBeHavior{ public void selfHealing() { System.out.println("我每秒回血2%n"); } }
/** * 慢速回血子类 * @author zhanyd */ public class SelfHealingSlow implements SelfHealingBeHavior{ public void selfHealing() { System.out.println("我每秒回血1%n"); } }
兵种类
/** * 兵种父类 * @author zhanyd */ public class Unit { protected String name; protected FightBeHavior fightBeHavior; protected SelfHealingBeHavior selfHealingBeHavior; public void move() { System.out.println("我是:" + name); System.out.println("向前挺进..."); } public void stop() { System.out.println("原地待命..."); } /** * 动态设置战斗方式 * @param fi */ public void setFightBeHavior(FightBeHavior fi) { fightBeHavior = fi; } /** * 动态设置自愈速度 * @param se */ public void setSelfHealingBeHavior(SelfHealingBeHavior se) { selfHealingBeHavior = se; } /** * 战斗 */ public void fight() { fightBeHavior.fight(); } /** * 自愈 */ public void selfHealing() { selfHealingBeHavior.selfHealing(); } }
/** * 步兵 * @author Administrator */ public class Infantry extends Unit{ public Infantry() { name = "步兵"; // 用剑攻击 fightBeHavior = new FightWithSword(); // 回血速度慢 selfHealingBeHavior = new SelfHealingSlow(); } }
/** * 弓箭手 * @author zhanyd */ public class Archer extends Unit{ public Archer() { name = "弓箭手"; // 用弓箭攻击 fightBeHavior = new FightWithArrow(); // 回血速度一般 selfHealingBeHavior = new SelfHealingNormal(); } }
/** * 骑士 * @author zhanyd */ public class Knight extends Unit{ public Knight() { name = "骑士"; // 用长枪攻击 fightBeHavior = new FightWithSpear(); // 回血速度快 selfHealingBeHavior = new SelfHealingFast(); } }
/** * 投石车 * @author zhanyd */ public class Catapult extends Unit{ public Catapult() { name = "投石车"; // 用石头攻击 fightBeHavior = new FightWithStone(); // 不能回血,不用设置回血功能 } }
测试类
public class TestUnit { public static void main(String[] args) { // 步兵出击 Unit unit = new Infantry(); unit.move(); unit.fight(); unit.stop(); unit.selfHealing(); // 弓箭手出击 unit = new Archer(); unit.move(); unit.fight(); unit.stop(); unit.selfHealing(); // 骑士出击 unit = new Knight(); unit.move(); unit.fight(); // 骑士扔掉了长枪,拔出了宝剑 System.out.println("动态设置:骑士扔掉了长枪,拔出了宝剑!"); unit.setFightBeHavior(new FightWithSword()); unit.fight(); unit.stop(); unit.selfHealing(); // 投石车出击 unit = new Catapult(); unit.move(); unit.fight(); unit.stop(); // 修理工给投石车做了保养,投石车也能回血了 System.out.println("动态设置:修理工给投石车做了保养,投石车也能回血了"); unit.setSelfHealingBeHavior(new SelfHealingSlow()); unit.selfHealing(); } }
测试结果
我是:步兵 向前挺进... 攻击:看我的剑法 原地待命... 我每秒回血1% 我是:弓箭手 向前挺进... 攻击:我射箭--> 原地待命... 我每秒回血2% 我是:骑士 向前挺进... 攻击:看我的长枪 动态设置:骑士扔掉了长枪,拔出了宝剑! 攻击:看我的剑法 原地待命... 我每秒回血3% 我是:投石车 向前挺进... 攻击:我扔石头 原地待命... 动态设置:修理工给投石车做了保养,投石车也能回血了 我每秒回血1%
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算