策略模式

2017-12-24  本文已影响0人  yishurensheng

概念

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

设计原则

  1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起;
  2. 针对接口编程,而不是针对实现编程;
  3. 多用组合,少用继承;

要点

UML图

UML图原地址

strategy.png

代码实现

先把代码贴上去,后面再慢慢解释。

Java版本

         此版本的代码只是先实现了MallardDuck和ModelDuck这两个类的鸭子,然后进行了一些测试。剩下的RubberDuck、DecoyDuck以及RedHeadDuck都没有实现,读者如果有兴趣的话,可以自己尝试实现并进行相关的测试。

FlyBehavior.java

package strategy;

/**
 * 所有飞行行为类必须实现的接口
 * @author ysrs
 *
 */
public interface FlyBehavior
{
    public void fly();
}

FlyNoWay.java

package strategy;

/**
 * 新的FlyBehavior类型,它不具有飞行能力
 * @author ysrs
 *
 */
public class FlyNoWay implements FlyBehavior 
{
    // 这是飞行行为的实现,给“不会”飞的鸭子用(包括橡皮鸭和诱饵鸭)
    @Override
    public void fly()
    {
        System.out.println("I can't fly!");
    }
}

FlyRocketPowered.java

package strategy;

/**
 * 新的FlyBehavior类型,它具有火箭般的飞行能力
 * @author ysrs
 *
 */
public class FlyRocketPowered implements FlyBehavior
{
    @Override
    public void fly()
    {
        System.out.println("I'm flying with a rocket!");
    }
}

FlyWithWings.java

package strategy;

/**
 * 新的FlyBehavior类型,它具有普通的使用翅膀的飞行能力
 * @author ysrs
 *
 */
public class FlyWithWings implements FlyBehavior
{
    // 这是飞行行为的实现,给”真会”飞的鸭子用。。。
    @Override
    public void fly()
    {
        System.out.println("I'm flying!!");
    }
}

QuackBehavior.java

package strategy;

/**
 * 所有呱呱叫行为类必须实现的接口
 * @author ysrs
 *
 */
public interface QuackBehavior
{
    public void quack();
}

Quack.java

package strategy;

/**
 * 新的QuackBehavior类型,它具呱呱叫的能力
 * @author ysrs
 *
 */
public class Quack implements QuackBehavior
{
    @Override
    public void quack()
    {
        System.out.println("Quack!");
    }
}

Squeak.java

package strategy;

/**
 * 新的QuackBehavior类型,它具有吱吱叫的能力
 * @author ysrs
 *
 */
public class Squeak implements QuackBehavior
{
    @Override
    public void quack()
    {
        System.out.println("Squeak");
    }
}

MuteQuack.java

package strategy;

/**
 * 新的QuackBehavior类型,它不具有叫的能力
 * @author ysrs
 *
 */
public class MuteQuack implements QuackBehavior
{
    @Override
    public void quack()
    {
        System.out.println("<< Silence >>");
    }
}

Duck.java

package strategy;

/**
 * Duck(鸭子)类
 * @author ysrs
 *
 */
public abstract class Duck
{
    // 为行为接口声明两个引用变量,
    // 所有鸭子子类(在同一个package中)都继承它们
    protected FlyBehavior flyBehavior;
    protected QuackBehavior quackBehavior;
    
    public Duck()
    {
        
    }
    
    public abstract void display();
    
    public void performFly()
    {
        // 委托给行为类
        flyBehavior.fly();
    }
    
    public void performQuack()
    {
        // 委托给行为类
        quackBehavior.quack();
    }
    
    public void swim()
    {
        System.out.println("All ducks float, even decoys!");
    }
    
    // 有了下面这两个函数后,以后就可以“随时”的调用这两个方法来改变鸭子的行为
    public void setFlyBehavior(FlyBehavior flyBehavior)
    {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior)
    {
        this.quackBehavior = quackBehavior;
    }
}

MallardDuck.java

package strategy;

/**
 * MallardDuck(绿头鸭)类
 * @author ysrs
 *
 */
public class MallardDuck extends Duck
{
    // 因为MallardDuck类是继承Duck类,所以具有
    // quackBehavior和flyBehavior实例变量
    public MallardDuck()
    {
        // 绿头鸭使用Quack类处理呱呱叫,所以当performQuack()
        // 函数被调用时,叫的职责被委托给Quack对象,而我们得到
        // 了真正的呱呱叫,而不是吱吱叫或者叫不出声。
        quackBehavior = new Quack();
        // 使用FlyWithWings作为FlyBehavior类型
        flyBehavior = new FlyWithWings();
    }
    
    public void display()
    {
        System.out.println("I'm a real Mallard duck!");
    }
}

ModelDuck.java

package strategy;

/**
 * 新的鸭子类型,模型鸭
 * @author ysrs
 *
 */
public class ModelDuck extends Duck
{
    public ModelDuck()
    {
        // 一开始,我们的模型鸭是不会飞的。
        flyBehavior = new FlyNoWay();
        quackBehavior = new Quack();
    }
    
    public void display()
    {
        System.out.println("I'm a model duck!");
    }
}

MiniDuckSimulator.java

package strategy;

/**
 * 测试类,对MallardDuck和ModelDuck两个类进行测试
 * @author ysrs
 *
 */
public class MiniDuckSimulator
{
    public static void main(String[] args)
    {
        System.out.println("-----------------------------------------");
        System.out.println("Test Model MallardDuck!");
        Duck mallard = new MallardDuck();
        // 这会调用MallardDuck继承来的performQuack()方法,进而委托给该对象的QuackBehavior
        // 对象处理,也就是说调用继承来的quackBehavior引用对象的quack()方法。
        mallard.performQuack();
        // 和performQuack()方法一样
        mallard.performFly();
        
        System.out.println("\n-----------------------------------------");
        System.out.println("Test Model Duck!");
        Duck model = new ModelDuck();
        // 第一次调用performFly()函数,会被委托给FlyBehavior对象
        // (也就是FlyNoWay实例),该对象是在模型鸭构造函数中设置的。
        model.performFly();
        // 这会调用继承来的setter方法,把火箭动力飞行的行为设定到模型鸭中。
        // 那么,模型鸭就突然具有了火箭动力飞行能力!
        model.setFlyBehavior(new FlyRocketPowered());
        // 如果设置成功了,就意味着模型鸭可以动态的改变它的飞行行为。
        // 如果把行为的实现帮死在鸭子类中,可就无法做到这样了。
        model.performFly();
    }
}

输出结果:

-----------------------------------------
Test Model MallardDuck!
Quack!
I'm flying!

-----------------------------------------
Test Model Duck!
I can't fly!
I'm flying with a rocket!
上一篇 下一篇

猜你喜欢

热点阅读