[菜鸟的设计模式之旅]策略模式

策略模式

定义

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

我的理解就是:比如我们接下来要说到的鸭子案例,有的鸭子可以飞,而飞又分为很多种,飞很高,飞得很低各种,我们就会把飞这个行为定义为接口,然后再分别去实现,而我们的鸭子只需要注入“飞”的行为,就可以去飞,至于怎么飞,鸭子不用去管,这也算是面向接口编程吧。当然除了飞,还有很多行为,我们都可以把这些行为抽成接口,然后再具体实现,让鸭子有接口类型的变量,就有了对应的行为啦~当然鸭子也分很多种,比如橡皮泥鸭子,这是肯定不能飞行的,那么我们就不需要去给他设置飞行实现就好了。非常的灵活,可以面对各种变化,  比如鸭子受伤了,不能飞了,那就修改下鸭子注入的飞行行为的实现,再比如鸭子又多了一种技能,能呱呱叫了,那就再写一个呱呱叫接口,至于怎么呱呱叫,让具体的实现去解决。

接下来我来粘贴一下《Head First 设计模式》上的案例即鸭子

举例

首先是鸭子抽象类:

我定义了一个FlyBehavior类型的变量,这个FlyBehavior是一个飞行行为的接口,这就意味着鸭子有了飞行行为

至于怎么飞,我们不需要考虑,交给飞行的实现去飞,也就是performFly(),同时还有一个setFlyBehavior(),这个方法就意味着,鸭子能够在运行时动态的修改自己飞行的实现,比如本来是“飞的很高”,后来鸭子年纪大了,飞不了很高了,那就用这个方法修改一下自己的飞行实现。比如duck.setFlyBehavior(new FlyLow());

package object;

import behaviour.FlyBehavior;

public abstract class Duck {

    protected FlyBehavior flyBehavior;

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public abstract void swim();
    public abstract void display();

    public void performFly(){
        flyBehavior.fly();
    }
}

有了抽象类肯定要有实现类呀,这就奉上香喷喷的"驯化野鸭”

flyBehavior的变量是从父类Duck继承过来的,而FlyWithWings是实现了FlyBehavior接口的"用翅膀飞行”,MallardDuck的构造函数就意味着,"驯化野鸭"对飞行行为的描述默认是“用翅膀飞行”,当然如果想改变它的飞行行为,那么只需要用刚刚提到的父类中的setFlyBehavior()方法就好了

package object.concreteobject;

import behaviour.FlyWithWings;
import object.Duck;

public class MallardDuck extends Duck{

    public MallardDuck(){
        flyBehavior = new FlyWithWings();
    }

    @Override
    public void swim() {
        // TODO Auto-generated method stub
        System.out.println("I'm swimming!");
    }

    @Override
    public void display() {
        System.out.println("I'm a real Mallard duck");
    }

}

当然,既然是粘贴代码,就一定要粘贴全,这就附上FlyBehavior接口和两个实现类,为了方便我就放在一起了。

package behaviour;

public interface FlyBehavior {

    void fly();
}

package behaviour;

public class FlyWithWings implements FlyBehavior{

    @Override
    public void fly() {
        System.out.println("flywithwings");
    }
}

package behaviour;

public class FlyNoWay implements FlyBehavior {

    @Override
    public void fly() {
        System.out.println("I can't fly");
    }

}

接下来我们就可以测试这只“驯化野鸭”的飞行行为了。

测试当中呢,首先先飞行了一下,当然会展示“驯化野鸭”的默认飞行行为,即“flywithwings”,随后小鸭子不小心受伤了它暂时不能飞行了,我们给它动态地重新设置了飞行行为,最后伤好了,自然又可以飞行了,然后只需要再重新设置就好了~

package test;

import behaviour.FlyNoWay;
import behaviour.FlyWithWings;
import object.Duck;
import object.concreteobject.MallardDuck;

public class Test {

    public static void main(String[] args) {
        Duck mallard = new MallardDuck();
        mallard.performFly();

        System.out.println("------------------------------");
        System.out.println("我不小心受伤了,这段时间我不能飞行了。。。");
        System.out.println("------------------------------");

        mallard.setFlyBehavior(new FlyNoWay());
        mallard.performFly();

        System.out.println("------------------------------");
        System.out.println("我有恢复健康了~");
        System.out.println("------------------------------");

        mallard.setFlyBehavior(new FlyWithWings());
        mallard.performFly();
    }
}

看,说的没错吧。。。。

这基本就是我对策略模式的学习总结吧,这个案例也是《Head First设计模式》中的,鸭子(各种鸭子), 各种行为(行为1[具体的行为1,具体的行为2.......],行为2[具体的行为1,具体的行为2.......]        .......),鸭子有很多种类,有的特殊的鸭子肯定有特殊行为,而行为可能一时也不好总结,谁知道哪天又会横空出世一种行为呢? 鸭子可以通过策略模式,动态地绑定行为,而新增行为,只需要再写个接口,随后再Duck类中加上对应的类型的变量就好了。(我还是再写一下吧,看看自己是不是真的理解了。。)

举例

本来想继续扩展鸭子,但是看到书上有另一案例。。

接下来就是粘贴代码了,粗略的写了一下,大概情节就是,角色: 有公主和骑士...,有两种行为,使用武器,跳舞,默认公主不会跳舞,和用匕首刺杀,而骑士可以用宝剑刺杀,没有跳舞行为。随后公主学了跳舞,变有了快乐地跳起了舞~

两种行为:

package behaviour;

/**
 * 跳舞
 *
 * @author DeepSleeping
 *
 */
public interface DanceBehavior {

    void dance();
}

package behaviour;

/**
 * 可以使用武器
 * @author DeepSleeping
 *
 */
public interface WeaponBehavior {

    void useWeapon();
}

两种行为对应的具体实现(表现):

package behaviour;

/**
 * 快乐地跳舞
 *
 * @author DeepSleeping
 *
 */
public class DanceHappy implements DanceBehavior {

    @Override
    public void dance() {
        System.out.println("快乐地跳舞!");
    }

}

package behaviour;

/**
 * 不可能跳舞
 *
 * @author DeepSleeping
 *
 */
public class DanceNoWay implements DanceBehavior {

    @Override
    public void dance() {
        System.out.println("我怎么可能会跳舞!");
    }

}

package behaviour;

/**
 * 使用匕首
 *
 * @author DeepSleeping
 *
 */
public class KnifeBehavior implements WeaponBehavior {

    @Override
    public void useWeapon() {
        System.out.println("-使用匕首刺杀-");
    }

}

package behaviour;

/**
 * 使用宝剑
 *
 * @author DeepSleeping
 *
 */
public class SwordBehavior implements WeaponBehavior {

    @Override
    public void useWeapon() {
        System.out.println("-使用宝剑刺杀-");
    }

}

角色,以及角色下的 公主、骑士

package object;

import behaviour.DanceBehavior;
import behaviour.WeaponBehavior;

/**
 * 角色
 *
 * @author DeepSleeping
 *
 */
public abstract class Character {

    WeaponBehavior wb;
    DanceBehavior db;

    public void setDb(DanceBehavior db) {
        this.db = db;
    }

    public void setWb(WeaponBehavior wb) {
        this.wb = wb;
    }

    /**
     *战斗
     */
    public void fight() {
        wb.useWeapon();
    }

    /**
     * 跳舞
     */
    public void dance() {
        db.dance();
    }
}

package object;

import behaviour.DanceNoWay;
import behaviour.SwordBehavior;

/**
 * 骑士
 *
 * @author DeepSleeping
 *
 */
public class Knight extends Character {

    public Knight() {
        // 默认骑士是用宝剑的
        wb = new SwordBehavior();
    }
}

package object;

import behaviour.DanceNoWay;
import behaviour.KnifeBehavior;

/**
 * 公主
 * @author DeepSleeping
 *
 */
public class Queen extends Character{

    public Queen(){
        //默认公主是用匕首的
        wb = new KnifeBehavior();
        //默认公主不会跳舞
        db = new DanceNoWay();
    }
}

开始测试~

package test;

import behaviour.DanceHappy;
import behaviour.SwordBehavior;
import object.Character;
import object.Knight;
import object.Queen;

public class Test {

    public static void main(String[] args) {

        Character knight = new Knight();
        Character queen = new Queen();

        // 骑士去刺杀
        knight.fight();
        // 公主去刺杀
        queen.fight();

        // 公主换成用宝剑刺杀
        queen.setWb(new SwordBehavior());
        queen.fight();

        System.out.println("--------------------");
        queen.dance();
        // 公主学会了跳舞
        queen.setDb(new DanceHappy());
        queen.dance();
    }
}

 总结

           总结下几个不错的设计原则:

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

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

      3.多用组合,少用继承

好了 ,策略模式就认识到这了,通过学习,我也算是对策略模式有了初步的认识吧,中间写着写着感觉好像装饰者模式啊,哈哈,又有点蒙了,继续学习吧。。。

参考材料:《Head First设计模式》

(0)

相关推荐

  • JAVA设计模式之策略模式 - Strategy

    在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式. 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 ...

  • PHP设计模式之策略模式

    PHP设计模式之策略模式 策略模式,又称为政策模式,属于行为型的设计模式. Gof类图及解释 GoF定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换.本模式使得算法可独立于使用它的 ...

  • [PHP小课堂]PHP设计模式之策略模式

    [PHP小课堂]PHP设计模式之策略模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 设计模式之策略模式

    策略模式 Strategy Intro 策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的 Context. 策略模式是一种定 ...

  • 设计模式——策略模式

    什么是策略模式?策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化.举个例子? ...

  • PHP设计模式—策略模式

    定义: 策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 结构: Strategy(策略类):定义所有支持的算法的公 ...

  • 设计模式(22) 策略模式

    在策略模式中,一个类的行为或算法可以在运行时动态更改. GOF对策略模式的描述为: Define a family of algorithms, encapsulate each one, and m ...

  • 设计模式-策略模式

    示例 策略模式是我们工作中比较常用的一个设计模式,但是初次理解起来可能会有点困难,因此我们还是先看一个例子,假设现在需要开发一个画图工具,画图工具中有钢笔,笔刷和油漆桶,其中,钢笔可以用于描边,但不能 ...

  • 详解JAVA面向对象的设计模式 (二)、策略模式

    策略模式 Strategy 介绍 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式. 在策略模式中,我们创建表示各种策略的对象和 ...

  • TypeScript实现设计模式——策略模式

    策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户. --<大话设计模式> 策略模式主要用来解决当有多种相似算 ...