设计模式之策略模式

  策略(Strategy)模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法时处理策略。简单来说,策略模式定义了一个算法家族,并让这些算法可以互换

       传统模式是通过继承处理多种算法或行为。该方式需要大量的子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起继承使得动态改变算法或行为变得不可能(每一个子类只能实现特定的算法)

        策略模式是对一系列算法的封装,即:为所有的算法定义一个抽象的算法接口(可以是接口,也可以是抽象类),并由具体的策略对象对算法进行实现。具体的算法选择交由具体策略类决定(具体策略类持有策略接口的引用)。

  本模式的核心思想是:多态(面向接口编程),组合【替代继承关系】

 

1. 传统模式【通过继承实现】

    1.1 父类【Duck.java】

  定义主要功能方法的通用实现。

public class Duck {
    public void swim() {
        System.out.println("I can swim.");
    }
}
Duck.java

    1.2 继承对象类

           实现自己的特有逻辑

public class FreeStrokeDuck extends Duck {
    @Override
    public void swim() {
        System.out.println("I can free stroke.");
    }
}

public class BreaststrokeDuck extends Duck {
    @Override
    public void swim() {
        System.out.println("I can breaststroke.");
    }
}
子类

    1.3 Demo

public static void main(String[] args) {
      Duck duck = new FreeStrokeDuck();
      duck.swim();
}
demo

 

2. 策略模式

        将对象分为三种角色:1.抽象策略角色,2.具体策略角色,3.环境角色

    2.1 抽象策略角色

       为算法定义一个抽象的算法接口

public interface Duck {
    void swim();
}
Duck.java

    2.2 具体策略角色

       实现抽象策略角色,根据具体的业务需求,实现特定的算法

public class FreeStrokeDuck implements Duck{
    @Override
    public void swim() {
        System.out.println("I can free stroke.");
    }
}


public class BreaststrokeDuck implements Duck {
    @Override
    public void swim() {
        System.out.println("I can breaststroke.");
    }
}
View Code

    2.3 环境角色

      策略的外部封装类,或者说策略的容器类。根据不同策略执行不同的行为。

public class Skill {

    //策略角色的引用,多态原理
    Duck duck;

    public Skill(Duck duck) {
        this.duck = duck;
    }

    public void swim() {
        duck.swim();
    }
}
Skill.java

    2.4 Demo

/**
 *  避免接口对外暴露后被篡改
 */
public static void main(String[] args) {
    Skill skill = new Skill(new FreeStrokeDuck());
    skill.swim();
}
        
demo

 

3. 枚举+ lambda表达式

    3.1 定义策略角色

public interface Skill {
    void swim();
}
Skill.java

    3.2 创建枚举类

public enum SkillEnum {

    /**
     * 使用lamda表达式实现Skill接口
     */
    FREE_SKROKE(() -> {
        System.out.println("I can free stroke.");
    }),
    BREAST_STROKE(() -> {
        System.out.println("I can breaststroke.");
    });

    private Skill skill;
    SkillEnum(Skill skill) {
        this.skill = skill;
    }

    public Skill getSkill() {
        return skill;
    }
}
SkillEnum.java

    3.3 创建环境角色

public class Duck {

    private SkillEnum skill;

    public Duck(SkillEnum skill) {
        this.skill = skill;
    }

    public void swim() {
        skill.getSkill().swim();
    }
}
Duck.java

    3.4 Demo

public static void main(String[] args) {
    Duck duck = new Duck(SkillEnum.BREAST_STROKE);
    duck.swim();
}
demo

 

4. 补充

    4.1 继承是在编译时静态决定类的行为,组合是在运行时动态地拓展对象的行为。而且,通过动态地组合对象,可以写新的代码添加新功能,而无须修改现有的代码(出现Bug的概率会变低)。

 

5. 参考资料

    5.1 北风网在线培训《策略模式》

    5.2 百度百科《策略模式》

    5.3 O'Reilly《Head First设计模式》

 

posted @ 2019-01-16 14:16  blue星空  阅读(440)  评论(0编辑  收藏  举报