策略模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法时的处理策略。
本模式的核心思想是:多态(面向接口编程)。【本质上就是对继承的灵活使用】
1. 策略模式1.0
将对象分为三种角色:1.抽象策略角色,2.具体策略角色,3.环境角色
1.1 抽象策略角色【Duck.java】
抽象策略角色通常是一个抽象类,将共有的方法抽到这个类里面。(该类作为超类,具体策略类可以继承该类,实现对抽象类方法的继承或重写)
public abstract class Duck { public abstract void swim(); public void scream() { //TODO } }
1.2 具体策略角色【FlyDuck.java】
具体策略类,实现自己的特有逻辑
public class FlyDuck extends Duck { @Override public void swim() { // TODO } }
1.3 环境角色【DUckUtils.java】
环境角色,持有策略角色的引用,供外部调用
public class DuckUtils { private Duck duck; public DuckUtils(Duck duck) { super(); this.duck = duck; } public void siwm() { duck.swim(); } public void scream() { duck.scream(); } }
1.4 Demo
public static void main(String[] args) { DuckUtils duck = new DuckUtils(new FlyDuck()); duck.siwm(); }
【个人认为环境角色没有必要,完全可以直接通过抽象策略角色【Duck.java】调用方法(多态的思想)】
【或许是个人没有理解到环境角色的重要作用,欢迎大家交流思想】
2. 策略模式2.0
该版本移除了环境角色【DUckUtils.java】,直接将抽象策略角色供外部调用
2.1 Demo
public static void main(String[] args) { Duck duck = new FlyDuck(); duck.swim(); }
【对于某些具体策略角色的特有方法(并非所有的具体策略角色都有该方法),肯定不能在抽象策略角色中添加,所以就需要提供特殊的接口来实现这些特殊的方法(这样,当需求改变后,该方法不再需要时,只需要移除接口,就可通过级联的关系移除相应的代码,避免遗漏)】
3. 策略模式3.0
该模式将其它特有的方法抽象成接口,供有需要的具体策略角色实现。依照的原理是:单继承,多实现。
3.1 接口【Flyable.java】
public interface Flyable { void fly(); }
3.2 具体策略角色【FlyDuck.java】
public class FlyDuck extends Duck implements Flyable{ @Override public void fly() { // TODO } @Override public void swim() { // TODO } }
3.3 Demo
public static void main(String[] args) { Duck duck = new FlyDuck(); if(duck instanceof FlyDuck){ ((FlyDuck) duck).fly(); } }
【当具体策略对象有很多的时候,每一次创建实例的时候必须熟悉具体策略角色的具体名称才能创建实例。因此,想到可以将实例的创建委托给 工厂模式】
4. 策略模式4.0
该模式将结合工厂模式,即:将对象的创建委托给工厂模式
4.1 工厂类【DuckFactory.java】
public class DuckFactory { public static final String DUCK_TYPE_FLYDUCK = "fly"; public static Duck createDuck(String type){ if(DUCK_TYPE_FLYDUCK.equals(type)){ return new FlyDuck(); }else{ return null; } } }
4.2 Demo
public static void main(String[] args) { Duck duck = DuckFactory.createDuck(DuckFactory.DUCK_TYPE_FLYHEAT); duck.swim(); if(duck instanceof FlyDuck){ ((FlyDuck) duck).fly(); } }