首页 > 代码库 > 设计模式(1)--策略模式

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

什么是策略模式呢?

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

  上面的定义你明白了吗?

  我觉得聪明伶俐的你肯定已经明白了,那你看看我是怎么理解的吧。

  就是将一个基类中一些行为进行分类,然后在应用到具体的类中选择这些具体的类别,下面我们举个例子来看看。

深入理解策略模式

  假如现在有个需求,要求你写一个鸭子基类,这个鸭子基类要求有三个方法,分别是quak、fly、display,具体的鸭子种类继承这个基类。

  根据这个需求,首先想到的应该是这样的

public class Duck {

    private String color;

    public Duck() {
    }

    public Duck(String color) {
        super();
        this.color = color;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void quake() {
        System.out.println("嘎嘎嘎...");
    }

    public void display() {
        System.out.println("我是一只" + color + "的鸭子");
    }

    public void fly() {
        System.out.println("飞啊飞啊...");
    }
}

 

  这个基类完成后,其他的具体鸭子继承这个基类,然后在写其他的特有属性或方法。

  但是呢?这是不是存在一些问题呢?所有的鸭子都是‘嘎嘎嘎’的叫吗,所有的鸭子都能飞吗?我觉得肯定有一些比较奇葩的鸭子...所以呢我们这个设计存在这问题,此时应该怎么解决呢?这时候你应该会想到吧这个定义成一个接口,让其他的子类去实现它。具体代码应该如下:

public interface BaseDuck {

    void quak();

    void display();

    void fly();
}

  或者我们也可以定义一个抽象类,将一些不怎么需要变化的方法在基类实现,而另外一些方法由子类去实现,示例如下:

public abstract class AbstractDuck {

    private String color;

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public abstract void quak();

    public void display() {
        System.out.println("我是一只" + color + "的鸭子");
    }

    public abstract void fly();
}

  这时候这个代码还行,但是它真的没有缺陷了吗?可能忽略了一个问题,那就是我们这种设计是为了适应那些比较奇葩的鸭子种类。其他大部分鸭子应该都是一样的叫声和是可以进行飞行的。那么我们在写子类的时候就会写很多冗余的代码,那么我们如何解决这个问题呢?

  策略模式就是解决这种问题的,它是如何实现的呢?先分析这个基类,quak和fly这两个是容易变化的,客户说不定那一天就要你加一个玩具鸭什么的。所以就这两个行为寄抽取出来,单独进行编写。先定义两个接口QuakBehavior和FlyBehavior,然后在根据需求编写一些子类,如能飞和不能飞、‘嘎嘎嘎’和‘吱吱吱’和不会叫等。示例代码如下:

  下面代码是多个文件

//QuackBehavior.java
public interface QuackBehavior {

    void quak();
}

//FlyBehavior.java
public interface FlyBehavior {

    void fly();
}

//Quack.java
public class Quack implements QuackBehavior {

    @Override
    public void quak() {
        System.out.println("嘎嘎嘎...");
    }

}

//Squeak.java
public class Squeak implements QuackBehavior {

    @Override
    public void quak() {
        System.out.println("吱吱吱...");
    }

}

//QuackNoWay.java
public class QuackNoWay implements QuackBehavior {

    @Override
    public void quak() {
        System.out.println("我不会叫...");
    }

}

//FlyWithWings.java
public class FlyWithWings implements FlyBehavior {

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

}

//FlyNoWay.java
public class FlyNoWay implements FlyBehavior {

    @Override
    public void fly() {
        System.out.println("我不会飞...");
    }

}

  基类应该这样设计:

package model.strategy.v2;

public class Duck {

    private String color;

    //添加行为接口的字段
    private QuackBehavior quackBehavior;

    private FlyBehavior flyBehavior;

    public Duck() {
    }

    public Duck(String color, QuackBehavior quackBehavior, FlyBehavior flyBehavior) {
        super();
        this.color = color;
        this.quackBehavior = quackBehavior;
        this.flyBehavior = flyBehavior;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void quake() {
     //调用接口方法 quackBehavior.quak(); }
public void display() { System.out.println("我是一只" + color + "的鸭子"); } public void fly() {
     //调用接口方法 flyBehavior.fly(); } }

  现在想想这个问题是不是很好的解决了!如果新的需求来了,我们只要定义一个新的接口实现了,而不需要修改这个基类中的代码。

  我相信这时候已经对策略模式理解的很好了,如果你对该博客有什么见解或疑问,可以留言哦>v<

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