设计模式-策略模式

策略模式

  • 问题背景
  • 解决方案:传统方式
  • 策略模式
    • 基本介绍
    • UML类图
  • 使用策略模式解决问题
    • UML类图
    • 代码示例
  • 注意事项和细节

问题背景

编写一个鸭子项目
1、有各种各种的鸭子,他们有各种行为,例如游泳,飞行,叫等
2、野鸭会飞,会游泳,会叫
3、水鸭不会飞,会游泳,会叫
4、玩具鸭不会飞,不会游泳,会叫
展示这些鸭子的行为

解决方案:传统方式

我们来想想传统的解决方式

1、每一个鸭子都写一个类,这样确实没有什么问题。但是它的缺点就是方法不能复用,重复的方法要写好多。

2、我们比较一看上面的信息,我们发现,其实他们就是三种行为,只不过对这三种行为有不同的表现,例如,飞行,野鸭会飞,水鸭和玩具鸭不会。

3、所以我们就就来向上抽象,抽象类中实现所有的方法, 不同的鸭子如果和抽象类不同,那就在子类中重写方法。

4、但是这样也不对,其实对于水鸭和玩具鸭本质就是不会飞的。

4、这就是继承带来的问题,对类的局部改动,尤其是超类的局部改动,会影响其他部分,会有溢出效应

策略模式

基本介绍

1)策略模式(Strategy Pattern)中,定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
(就是对我们的鸭子的行为单独拿出来做一个接口,然后实现不同的行为,例如将飞行这种行为拿出来作为接口,然后再继承这个接口实现会飞,飞的不好,不会飞这三种形式,不同的鸭子传入不同的形式就可以了)

2)这算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体类(定义了策略接口);第三、多用组合/聚合,少用继承(客户通过组合方式使用策略)

UML类图

设计模式-策略模式_第1张图片
从上面的类图我们可以看到,Context类有成员变量StrategyA和StrategyB接口,需要那个接口我们就在构造器中执行。

使用策略模式解决问题

UML类图

设计模式-策略模式_第2张图片

代码示例

/**
 * 鸭子抽象类
 */
public abstract class Duck {

    public void quack() {
        System.out.println("会叫");
    }
}
/**
 * 飞行行为
 */
public interface FlyBehavior {
    void fly();
}
/**
 * 游泳行为
 */
public interface SwimBehavior {
    void swim();
}
/**
 * 水鸭
 */
public class TealDuck extends Duck{

    private SwimBehavior swimBehavior;

    private FlyBehavior flyBehavior;

    private String name = "水鸭";

    public String getName() {
        return name;
    }

    public TealDuck(SwimBehavior swimBehavior, FlyBehavior flyBehavior) {
        this.swimBehavior = swimBehavior;
        this.flyBehavior = flyBehavior;
    }

    public void swim() {
        if (swimBehavior != null) {
            swimBehavior.swim();
        }
    }

    public void fly() {
        if (flyBehavior != null) {
            flyBehavior.fly();
        }
    }
}
/**
 * 野鸭
 */
public class WildDuck extends Duck{

    private SwimBehavior swimBehavior;

    private FlyBehavior flyBehavior;

    private String name = "野鸭";

    public String getName() {
        return name;
    }

    public WildDuck(SwimBehavior swimBehavior, FlyBehavior flyBehavior) {
        this.swimBehavior = swimBehavior;
        this.flyBehavior = flyBehavior;
    }

    public void swim() {
        if (swimBehavior != null) {
            swimBehavior.swim();
        }
    }

    public void fly() {
        if (flyBehavior != null) {
            flyBehavior.fly();
        }
    }
}
/**
 * 玩具鸭
 */
public class ToyDuck extends Duck{

    private SwimBehavior swimBehavior;

    private FlyBehavior flyBehavior;

    private String name = "玩具鸭";

    public String getName() {
        return name;
    }

    public ToyDuck(SwimBehavior swimBehavior, FlyBehavior flyBehavior) {
        this.swimBehavior = swimBehavior;
        this.flyBehavior = flyBehavior;
    }

    public void swim() {
        if (swimBehavior != null) {
            swimBehavior.swim();
        }
    }

    public void fly() {
        if (flyBehavior != null) {
            flyBehavior.fly();
        }
    }
}

飞行行为

public class BadFlyBehavior implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("飞的不好");
    }
}
public class GoodFlyBehavior implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("飞的很好");
    }
}
public class NotFlyBehavior implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("不会飞");
    }
}

游泳行为

public class BadSwimBehavior implements SwimBehavior{
    @Override
    public void swim() {
        System.out.println("游的不好");
    }
}
public class GoodSwimBehavior implements SwimBehavior{
    @Override
    public void swim() {
        System.out.println("游的很好");
    }
}
public class NoSwimBehavior implements SwimBehavior{
    @Override
    public void swim() {
        System.out.println("不会游泳");
    }
}

测试类

public class Client {
    public static void main(String[] args) {
        ToyDuck toyDuck = new ToyDuck(new NoSwimBehavior(), new NotFlyBehavior());
        System.out.println(toyDuck.getName());
        toyDuck.quack();
        toyDuck.fly();
        toyDuck.swim();
        System.out.println("========================================================");

        WildDuck wildDuck = new WildDuck(new GoodSwimBehavior(), new GoodFlyBehavior());
        System.out.println(wildDuck.getName());
        wildDuck.quack();
        wildDuck.fly();
        wildDuck.swim();
        System.out.println("========================================================");

        TealDuck tealDuck = new TealDuck(new BadSwimBehavior(), new BadFlyBehavior());
        System.out.println(wildDuck.getName());
        wildDuck.quack();
        wildDuck.fly();
        wildDuck.swim();
        System.out.println("========================================================");
    }
}

测试结果

设计模式-策略模式_第3张图片

注意事项和细节

1)策略模式的关键是:分析项目中变化部分与不变部分
2)策略模式的核心思想是:多用组合/聚合,少用继承;用行为类组合,而不是行为的2继承。更有弹性
3)体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略 (或者行为) 即可,避免了使用多重转移语句 (if…else if…else)
4)提供了可以替换继承关系的办法:策略模式将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展
5)需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大

你可能感兴趣的:(设计模式,策略模式,设计模式,java)