设计模式之策略模式

  The Game Awards 2015主持人Geoff Keighley宣布将把今年的行业标志将(Industry Icon Award)颁给传奇工作室Westwood Studios的两位创始人。

  想起了2004年跟室友玩红警,那哥们造了满屏的坦克,浩浩荡荡的来推我的基地。坦克太多,多到我们那赛扬的机器卡地不要不要的。

  忽然好怀念那段时光,也不知道远在武汉的兄弟,现在如何。

  今天开始学习设计模式,就以红色警戒为例吧,也顺便缅怀一下大学时光。

 


  今天讲的是策略模式,先不讲定义,先看场景。

   游戏中会造很多大兵,每个大兵都有基本的走路、巡逻的功能。为了复用代码,我建立了一个父类,所有的兵种都继承自这个父类。

  那么问题来了,游戏运行起来,你会发现美国大兵、伞兵、解放军、尤里的攻击方式都一样。怎么办呢,有两个办法。

  1.在美国大兵、伞兵、解放军、尤里中覆盖父类的方法,这样攻击起来都使用各自的方法了,但是你发现其实美国大兵和伞兵的攻击方式其实是一样的,所以代码需要写两遍。

  2.把Soldier声明成接口,每个子类实现接口的方法。但是所有的兵种都有冲锋的功能,所有具体实现类都得不厌其烦的ctrl-C ctrl-V  rush的方法。一旦领导说开个加速,所有的兵rush的速度快一点, 。。。我得加班改所有子类的rush方法。

  我们可以看到,在父类中有的方法是变化的,有的是不变的,那就引出了我们的第一条设计原则:

 

找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起。

 怎么独立呢,首先想到的是把攻击变成一个接口类,所有兵种都实现这个接口,那么就变成这样:

  好啦,还是那个问题,美国大兵和伞兵攻击的方式其实是一样的,还是得ctrl-c ctrl-v。而且攻击方式变的话,俩都得改。而且万一大兵升级成了三等兵,攻击速度快了,或者攻击方式变了怎么办呢?接下来我们看第二个设计原则。

针对接口编程,而不是针对实现编程。

   我们利用接口代表每个行为,比如说fireable,行为的每个实现代表一种行为方式。各个兵种只需要包含一个行为方式的对象而不用实现这个接口。

  

  普通箭头是“有一个”的关系,带三角的箭头是“是一个”的关系。有一个就是组合(Composition)。这种做法和“继承”不同的地方在于,开火的行为不是继承来的,而是和适当的行为对象“组合”来的。

多用组合,少用继承

   现在可以说说策略模式的定义了:

 

策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

 

 java实现如下:

Fireable行为接口

package com.zzl.designpattern.strategy;

public interface IFireable {
    public void fire();
}

 

 

FireWithGun类

package com.zzl.designpattern.strategy;

public class FireWithGun implements IFireable {

    @Override
    public void fire() {
        System.out.println("使用左轮枪攻击");
    }
}

FireWithAK47类

package com.zzl.designpattern.strategy;

public class FireWithAK47 implements IFireable {

    @Override
    public void fire() {
        System.out.println("使用AK47攻击!");
    }
}

 

 Solider大兵抽象类

package com.zzl.designpattern.strategy;

public abstract class Solider {
    /**
    * 行为类
    */
    IFireable fireable;

    /**
    * 冲刺
    */
    public void rush(String direction){
        System.out.println("向 " + direction + " 冲刺");

    }
    /**
    * 升级
    */
    public abstract void  partrol();
    /**
    * 开火
    */
    public void fire(){
        fireable.fire();
    }
    /**
    * setFireable
    */
    public void setFireable(IFireable fireable){
        this.fireable = fireable;
    }
}
View Code

 

FootSolider美国大兵类

package com.zzl.designpattern.strategy;

public class FootSolider extends Solider {

    public FootSolider(){
        fireable = new FireWithGun();
        System.out.println("新建一个一级美国大兵");
    }

    @Override
    public void partrol() {
        System.out.println("美国大兵升级了!");
        this.setFireable(new FireWithAK47());
    }
}
View Code

 

Game游戏类

package com.zzl.designpattern.strategy;

public class Game {

    public static void main(String[] args) {
        Solider footSolider = new FootSolider();
        footSolider.rush("左");
        footSolider.fire();
        footSolider.partrol();
        footSolider.fire();
    }

}
View Code

 

运行结果

新建一个一级美国大兵
向 左 冲刺
使用左轮枪攻击
美国大兵升级了!
使用AK47攻击!
Console

 

posted @ 2015-12-02 15:34  周.class  阅读(191)  评论(0编辑  收藏  举报