java游戏策略模式_JAVA设计模式之策略模式

开发一款游戏,里面有各种鸭子,这些鸭子有共同点:会游泳、会叫;

1.设计超类Duck,里面有swim()方法和quack()方法,所有鸭子继承此超类,那么继承的对象便都有了游泳和叫的技能;

1 public abstract classDuck {2 /*所有的鸭子都会游泳*/

3 public voidswim() {4 System.out.println("I can swim");5 }6 /*所有的鸭子都会叫*/

7 public voidquack() {8 System.out.println("I can quack");9 }10 /*其它行为*/

11 public abstract voiddisplay();12 }

2.需求变更:增加三种叫的方法,不同的鸭子叫声不同,有“吱吱叫”、“呱呱叫”,还有不会叫;那么可以覆写每个子类quack()方法,使鸭子叫声不同。

3.需求变更:鸭子得会飞;那么可以为超类Duck增加fly()方法,所有继承的子类便有了飞的技能;

4.需求变更:有些鸭子不会飞;那么覆写每个鸭子的fly()方法,使不会飞的鸭子不能飞;

这里已经存在一些问题:每当有新的鸭子出现,都需要检查fly()方法和quack()方法,确认是否需要覆写。这种继承 and 覆写的方法很糟糕。

改变:

继承或许不可取,改用接口;可以把fly和quack提取为两个接口,会飞的实现flyable接口,会叫的实现quackable接口;

改用接口带来的麻烦:每个实现flyable或quackable的子类,都需要去覆写fly()方法和quack()方法,代码根本不能复用,导致做很多重复工作。

问题分析:鸭子的fly和quack的行为在子类中不断的变化,让子类都具有这些行为是不恰当的;使用flyable和quackable接口,虽然可以解决一部分问题,但是fly()和quack()方法需在每个子类中覆写,代码不能复用,会增加很多重复工作。

有种设计原则很适合这样的情况:

一、找出需求中可能变化之处,把它们独立出来,不和不变的代码混在一起;(可以把易于变化的代码封装起来,以便可以轻易的改动和扩充此部分,而不影响不需要改动的其它部分)。

二、针对接口编程而非针对实现。

三、多用组合,少用继承。

开始将fly行为和quack行为独立出来:

准备组建两组类(完全脱离Duck),一组是fly相关的(实现FlyBehavior接口),一组是quack相关的(实现QuackBehavior接口)。有:会飞(FlyWithWings)、不会飞(FlyNoWay)、呱呱叫(Quack)、吱吱叫(Squeak)、安静(MuteQuack)等类;

1 /*会飞*/

2 public class FlyWithWings implementsFlyBehavior {3

4 public voidfly() {5 System.out.println("I'm flying.");6 }7

8 }9 /*不会飞*/

10 public class FlyNoWay implementsFlyBehavior {11

12 public voidfly() {13 System.out.println("I can't fly.");14 }15

16 }17 /*呱呱叫*/

18 public class Quack implementsQuackBehavior {19

20 public voidquack() {21 System.out.println("呱!呱!");22 }23

24 }25 /*吱吱叫*/

26 public class Squeak implementsQuackBehavior {27

28 public voidquack() {29 System.out.println("吱!吱!");30 }31

32 }33 /*不会叫*/

34 public class MuteQuack implementsQuackBehavior {35

36 public voidquack() {37 System.out.println("<< Silence >>");38 }39

40 }

新设计中,鸭子的子类将使用接口(FlyBehavior和QuackBehavior)所表示的行为,子类不需要去实现特定的行为(之前的设计,每个子类需要实现不同的功能覆写,把子类与实现绑定),而是由FlyBehavior和QuackBehavior的实现类来实现特定的行为。

整合鸭子的行为:

1 public abstract classDuck {2

3 publicFlyBehavior flyBehavior;4 publicQuackBehavior quackBehavior;5

6 //可以动态的设定既成的行为

7 public voidsetFlyBehavior(FlyBehavior flyBehavior) {8 this.flyBehavior =flyBehavior;9 }10 public voidsetQuackBehavior(QuackBehavior quackBehavior) {11 this.quackBehavior =quackBehavior;12 }13

14 /**

15 * 其它行为16 */

17 public abstract voiddisplay();18

19 /**

20 * 能够表演飞和叫的行为21 */

22 public voidperformFly() {23 flyBehavior.fly();24 }25 public voidperformQuack() {26 quackBehavior.quack();27 }28

29 /**

30 * 所有鸭子都会游泳31 */

32 public voidswim() {33 System.out.println("I can swim.");34 }35 }

鸭子对象不亲自处理quack和fly的行为,而是由QuackBehavior和FlyBehavior接口的对象去处理。并且子类也可动态设定飞和叫的行为。

子类鸭子(绿头鸭)代码实例:

1 /**

2 * 绿头鸭3 *4 */

5 public class MallardDuck extendsDuck {6

7 publicMallardDuck() {8 flyBehavior = newFlyWithWings();9 quackBehavior = newQuack();10 }11

12 @Override13 public voiddisplay() {14 System.out.println("I'm a real mallard duck!");15 }16

17 }

测试代码的行为:

1 public classDuckTest {2

3 @Test4 public voidtest() {5 Duck mallard = newMallardDuck();6 mallard.swim();7 mallard.display();8 //行为没有被改变之前

9 mallard.performQuack();10 mallard.performFly();11 //行为改变之后

12 mallard.setQuackBehavior(newSqueak());13 mallard.setFlyBehavior(newFlyNoWay());14 mallard.performQuack();15 mallard.performFly();16

17 }18 }

运行结果:

I can swim.

I'm a real mallard duck!

呱!呱!

I'm flying.

吱!吱!

I can't fly.

本例中将鸭子与两种行为QuackBehavior和FlyBehavior接口类组合使用,弹性大,且易于维护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值