定义
其思想是针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换。策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能
类图
实例
毕业季,同学们面临很多选择: 工作、出国深造、考研...
Michael刚开始的时候选择的工作,但是工作两年之后发现还是热爱科研,然后选择了考研,使用策略模式该如何实现呢?
主体Context:
package com.ytj.demo.design.patterns.strategy; /** * Context * * @version V1.0.0 * @program: testMaven * @description: Context * @date 2019/9/10 13:14 */ class Context { private IStrategy strategy; private String name; Context(IStrategy strategy, String name) { this.strategy = strategy; this.name = name; } /** * 毕业选择 */ void developmentAfterGraduate() { System.err.println(name + "选择是: "); strategy.chooseYourFuture(); } }
站在毕业路口的选择:
package com.ytj.demo.design.patterns.strategy; /** * 策略接口 * * @version V1.0.0 * @program: testMaven * @description: IStrategy * @date 2019/9/10 13:05 */ public interface IStrategy { void chooseYourFuture(); } /** * 工作 */ class WorkStrategy implements IStrategy{ @Override public void chooseYourFuture() { System.err.println("上班吧,老老实实挣钱"); } } /** * 出国 */ class AbroadStrategy implements IStrategy { @Override public void chooseYourFuture() { System.err.println("出国吧,到外面看看"); } } /** * 考研 */ class PostgraduateStrategy implements IStrategy { @Override public void chooseYourFuture() { System.err.println("考个研究生吧,现在这就业形势这么严峻"); } }
看下测试类:
package com.ytj.demo.design.patterns.strategy; /** * StrategyTest * * @version V1.0.0 * @program: testMaven * @description: StrategyTest * @date 2019/9/10 13:15 */ public class StrategyTest { public static void main(String[] args) { // michael选择工作 Context michael = new Context(new WorkStrategy(), "michael"); michael.developmentAfterGraduate(); // 工作两年之后想考研 System.err.println("After two years: "); michael = new Context(new PostgraduateStrategy(), "michael"); michael.developmentAfterGraduate(); } }
输出如下:
michael选择是: 上班吧,老老实实挣钱 After two years: michael选择是: 考个研究生吧,现在这就业形势这么严峻
用法
- Spring中bean实例化策略
接口InstantiationStrategy是实例化策略接口类,它定义了三个实例化接口,然后SimpleInstantiationStrategy实现了该策略,它主要做一些简单的根据构造函数实例号bean的工作,然后CglibSubclassingInstantiationStrategy又继承了SimpleInstantiationStrategy新增了方法注入方式根据cglib生成代理类实例化方法。
在AbstractAutowireCapableBeanFactory中管理了该策略的一个对象,默认是CglibSubclassingInstantiationStrategy策略,运行时候可以通过setInstantiationStrategy改变实例化策略,如果你自己写个个策略的话。
AOP中的代理策略
首先看AopProxyFactory接口类提供了createAopProxy接口,这个是策略模式的接口方法。然后DefaultAopProxyFactory实现了该接口作为策略的实现者。然后ProxyCreatorSupport里面引用了AopProxyFactory,并且提供了get,set方法用来运行时改变策略,这里Spring只实现了DefaultAopProxyFactory这一个策略,如果需要自己也可以写个
本部分参考: 常用开源框架中设计模式使用分析- 策略模式
其他
策略模式的使用场景:
多个类只有再算法或行为上稍有不同的场景
算法需要自由切换的场景
需要屏蔽算法规则的场景
注意事项
如果系统中的一个策略家族的具体数量超过4个,则需要考虑使用混合模式(再加上工厂模式决定采取哪种策略),解决策略类膨胀和对外暴露的问题。