设计模式之禅(1)-策略模式

版权声明:需要引用、发表的朋友请与本人联系 https://blog.csdn.net/pbrlovejava/article/details/84198499


更多关于设计模式的文章请点击设计模式之禅(0)-目录页


一、进一步的改进

上面的动物园例子似乎已经足够地完善了,但是仔细想想并不是这样:当另一个SmallDog被创建时,它实现了BarkBehavior接口,但是它需要在自身的代码中去重写这个bark()方法,这个bark()方法的具体实现暴露在了SmallDog类中,当我们需要修改SmallDogbark()方法实现时,我们需要在这个类中去修改代码,这就造成了硬编码问题,那么应该怎么解决呢?

这里引申出策略模式的一个重要思想:使用组合,而不是实现

  • BigDogBark实现类
/**
 * @Auther: ARong
 * @Date: 2018/11/17 23:10
 * @Description:
 */
public class BigDogBark implements BarkBehavior {

    @Override
    public void bark() {
        System.out.println("Big Dog 汪汪汪...");
    }
}
  • BigDog可修改为
/**
 * @Auther: ARong
 * @Date: 2018/11/17 11:09
 * @Description: com.iteason.Animal.BigDog 继承 Animal的所有属性和方法并实现BarkBehavior
 */
public class BigDog extends Animal {
    private BarkBehavior barkBehavior;

    //构造方法
    public BigDog(String name) {
        super(name);
        //在运行时将BigDogBark向上转型为BarkBehavior
        barkBehavior = new BigDogBark();
    }
    public BigDog() {
    }

    //将bark()方法的具体实现委托给BarkBehavior的子类
    public void performBark(){
        barkBehavior.bark();
    }


    public BarkBehavior getBarkBehavior() {
        return barkBehavior;
    }

    public void setBarkBehavior(BarkBehavior barkBehavior) {
        this.barkBehavior = barkBehavior;
    }
}

BigDog类中组合了一个BarkBehavior的接口,在构造方法中新建一个BarkBehavior的实现类BigDogBark通过面向对象的特征:多态,在运行时确定由谁实现了BarkBehavior接口,并且将执行动作委托给了performBark()方法去调用barkBehavior.bark(),这就是一个简单的策略模式的应用了。

以上关系可用UML关系图来表达:
在这里插入图片描述

二、用策略模式组织类关系实例

在下面,你将看到一堆杂乱的类与接口,这是取自一个动作冒险游戏。你将看到代
表游戏角色的类,以及武器行为的类。每个角色一次只能使用一个武器,但是可以
在游戏的过程中换武器。你的工作是要弄清楚这一切…

这是HeadFirst设计模式中的一个问题,可以使用策略模式,画出一个UML图来表示他们的关系:用Character作为角色的超类,里边含有角色的共同属性以及可变的战斗武器接口、战斗模式接口对象;FightBehavior是战斗模式的接口,Quene和Random分别实现了队列战斗模式和随机战斗模式;WeaponBehavior是战斗武器接口,KnifeBehavior和GanBehavior分别是使用剑、枪作为武器。

在这里插入图片描述
* Character超类

/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:35
 * @Description: 角色超类,定义了角色的名字和武器使用方式以及战斗行为
 */
public abstract class Character {
    //角色名字
    private String name;

    //武器使用方式
    private WeaponBehavior weaponBehavior;

    //战斗行为
    private FightBehavior fightBehavior;

 

    //构造方法
    public Character(String name) {
        this.name = name;
    }

    public Character() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public WeaponBehavior getWeaponBehavior() {
        return weaponBehavior;
    }

    public void setWeaponBehavior(WeaponBehavior weaponBehavior) {
        this.weaponBehavior = weaponBehavior;
    }

    public FightBehavior getFightBehavior() {
        return fightBehavior;
    }

    public void setFightBehavior(FightBehavior fightBehavior) {
        this.fightBehavior = fightBehavior;
    }
}
  • WeaponBehavior接口
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:37
 * @Description: 定义了角色的武器使用方式
 */
public interface WeaponBehavior {
    public void userWeapon();
}
  • FightBehavior接口
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:38
 * @Description: 定义了角色的战斗行为
 */
public interface FightBehavior {
    public void fight();
}
  • KnifeBehavior实现类
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:42
 * @Description: WeaponBehavior的实现类,使用剑作为武器
 */
public class KnifeBehavior implements WeaponBehavior{

    @Override
    public void userWeapon() {
        System.out.println("使用剑战斗");
    }
}
  • GanBehavior实现类
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:43
 * @Description: WeaponBehavior的实现类,使用枪作为武器
 */
public class GanBehavior implements WeaponBehavior{

    @Override
    public void userWeapon() {
        System.out.println("使用枪战斗");
    }
}
  • Quene实现类
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:40
 * @Description: FightBehavior的实现类,使用队列战斗行为
 */
public class Quene implements FightBehavior{

    @Override
    public void fight() {
        System.out.println("队列战斗");
    }
}
  • Random实现类
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:42
 * @Description: FightBehavior的实现类,使用随机战斗行为
 */
public class Random implements FightBehavior{
    @Override
    public void fight() {
        System.out.println("随机战斗");
    }
}
  • GanFighter角色类
/**
 * @Auther: ARong
 * @Date: 2018/11/17 17:01
 * @Description: GanFighter是一个使用枪和随机战斗方式的角色
 */
public class GanFighter extends Character{

    //构造方法
    public GanFighter(String name){
        super.setName(name);
        super.setWeaponBehavior(new GanBehavior());
        super.setFightBehavior(new Random());
    }

    public GanFighter(){

    }


    //使用武器
    public void performWeapon(){
        super.getWeaponBehavior().userWeapon();
    }

    //战斗方式
    public void performFight(){
        super.getFightBehavior().fight();
    }

}

GanFight是一个使用枪和随机战斗方式的角色,所以在它的构造方法中,为它的战斗武器和方式接口创建了具体的实现类,使他拥有了以枪为武器和随机战斗的方式。

使用GanFighter类:

@Test
    public void userGanFighter(){
        GanFighter g_fighter = new GanFighter("G_Fighter");

        System.out.println(g_fighter.getName());
        g_fighter.performWeapon();
        g_fighter.performFight();
    }

在这里插入图片描述

如果你想让角色能更加地方便创建和使用,可以在使用方法时传递接口实现类的方式,从而达到要求:

/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:44
 * @Description: Fighter类是Character的子类,并且在构造方法中需要实例化WeaponBehavior接口和FightBehavior接口的子类
 */
public class Fighter extends Character{
    //构造方法
    public Fighter(String n){
        //在实例化Fighter时指定Fighter的名字
        super.setName(n);
    }

    public Fighter(){

    }

    //战斗武器
    public void performWeapon(WeaponBehavior w){
        super.setWeaponBehavior(w);
        super.getWeaponBehavior().userWeapon();
    }

    //战斗方式
    public void performFight(FightBehavior f){
        super.setFightBehavior(f);
        super.getFightBehavior().fight();
    }

}

使用Fighter类去创建一个使用剑和随机战斗方式的角色:

@Test
    public void userFighter(){

       Fighter ganFighter = new Fighter("剑神");

        System.out.println(ganFighter.getName());
        //使用剑
        ganFighter.performWeapon(new KnifeBehavior());
        //随机战斗方式
        ganFighter.performFight(new Random());
    }

运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/pbrlovejava/article/details/84198499