【设计模式】8. 策略模式

定义

Define a family of algorithms, encapsulate each one, and make them interchangeable.

定义一组算法,将每个算法封装起来,并且使他们之间可以互换。


类图

Strategy:抽象策略角色

策略、算法家族的抽象,通常为接口。定义每个算法必须具有的方法和属性。

public interface Strategy{
    public void algorithmInterface();
}

ConcreteStrategy:具体策略角色

实现抽象策略中的操作,定义具体的算法。

public class ConcreteStrategy1 implements Strategy {
    public void algorithmInterface(){

    }
}

Context:封装角色

也叫做上下文角色,起承上启下 封装作用。屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

public class Context {
    private Strategy strategy = null;

    public Context (Strategy s) {
        this.strategy = s;
    }
    //封装后的策略方法
    public void doAnything() {
        this.strategy.algorithmInterface();
    }
}

优点

  1. 算法可以自由切换
  2. 避免使用多重条件判断
  3. 扩展性良好

缺点

  1. 策略类数量增多
  2. 所有的策略类都需哟啊对外暴露:在实例化Context时,需要传入具体策略类;违反迪米特法则。

最后一条,可结合其他模式进行修正,例如工厂方法模式、代理模式、享元模式


使用场景

  1. 多个类只有在算法或行为上稍有不同的场景
  2. 算法需要自由切换的场景(例如算法由使用者决定)
  3. 需要屏蔽算法规则的场景

由于上文所述的缺点,策略模式很少单独使用。

策略枚举

public enum Calculator {
    ADD("+") {
        public int exec(int a, int b) {
            return a + b;
        }
    },
    SUB("-") {
        public int exec() {
            return a - b;
        }
    };
    
    String value = "";
    private Calculator(String value) {
        this.value = value;
    }
    //策略方法
    public abstract int exec(int a, int b);
}


public class Client {
    ....
    Calculator.ADD.exec(1, 2);
} 


【例】

Strategy策略角色

//fly策略(算法)
public interface FlyBehavior {
    public void fly();
}
public class FlyWithWings implements FlyBehavior {
    public void fly() {....}
}
public class FlyNoWay implements FlyBehavior {
    public void fly() {....}
}

//quack策略(算法)
public interface QuackBehavior {
    public void quack();
}
。。。


Context封装角色

public abstract class Duck {
    //为什么不implements这2个接口?
    //因为“组合优于继承”;这样就可以在运行时动态地改变行为。
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior; 

    public void setters(){...}...

    public abstract void display();

    public void performFly(){
        flyBehavior.fly(); //委托
    }
    public void performQuack() {
        quackBehavior.quack();
    }
}


对比模板方法模式

都是用来封装算法。

模板方法:使用继承来定义算法中的个别步骤

策略模式:通过对象组合,让客户可以选择算法实现









你可能感兴趣的:(设计模式)