原创

详解设计模式—策略模式(Strategy Pattern)

定义

Define a family of algorithms,encapsulate each one,and make them interchangeable.(定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。)

对象行为模式

角色

Context:封装类

也就是常见的上下文对象,在策略模式中起到封装的作用,使调用者看不到对策略和算法的具体使用。

Strategy:抽象策略

策略的抽象接口,通常使用接口实现,定义具体策略中的必要的属性和方法。

ConcreteStrategy:具体策略

实现了抽象策略的具体策略,实现了每一种策略的算法。

类图

20190719103514674.png

使用场景

  • 多个类只有在算法和行为上有不同。
  • 算法需要可以随时切换,交给调用者决定用哪个算法。
  • 不需要对外展示每种策略的具体算法实现,只需要记住每个算法是做什么的,以及如何使用的时候,可以使用策略模式。

优点

  • 使用的算法可以随意切换,因为都是实现的统一个接口。
  • 避免了在代码使用多层条件语句进行判断,结构不清晰。
  • 拓展性好。

缺点

  • 在一个策略接口的实现方式增加后,随之而来的就是策略类的增加。
  • 所有策略类都都需要对外暴露,也就是说调用者需要使用真的策略类。

注意事项

在具体实现中,若每一个策略接口的实现类超过了四个,那么就要考虑使用混合模式,以此来解决上边提到的策略类膨胀和对外暴露对的问题。

具体实现

抽象策略

interface Strategy{

    void doSomething();
}

两种具体策略

class ConcreteStrategy1 implements Strategy{

    @Override
    public void doSomething() {
        System.out.println("this is strategy1");
    }
}

class ConcreteStrategy2 implements Strategy{

    @Override
    public void doSomething() {
        System.out.println("this is strategy2");
    }
}

封装策略类

class StrategyContext {

    private Strategy strategy;

    public StrategyContext(Strategy strategy){
        this.strategy = strategy;
    }

    public void executeStrategy(){
        this.strategy.doSomething();
    }

}

调用者

public static void main(String[] args) {

        Strategy strategy1 = new ConcreteStrategy1();
        Strategy strategy2 = new ConcreteStrategy2();

        new StrategyContext(strategy1).executeStrategy();

        new StrategyContext(strategy2).executeStrategy();

    }

输出

this is strategy1
this is strategy2

总结

策略枚举是一个非常优秀和方便的模式,但是它受枚举类型的限制,每个枚举项都是public、final、static的,扩展性受到了一定的约束,因此在系统开发中,策略枚举一般担当不经常发生变化的角色。

它在项目中使用得非常多,但它单独使用的地方就比较少了,因为它有致命缺陷:所有的策略都需要暴露出去,这样才方便客户端决定使用哪一个策略。

参考

设计模式
设计模式之禅

sev7e0
Write by sev7e0
end
本文目录