【设计模式】策略模式

来源:互联网 发布:恒大淘宝内部组织架构 编辑:程序博客网 时间:2024/05/21 16:57

策略模式是一种很常用的模式,尽管他有一些缺点,但是在我们日常代码中依旧经常用到,另外大家可以看Spring的AopProxy就有用到,今天比较晚了,下次抽时间给大家带来那段源码解析。

    首先来看策略模式的定义:定义一组算法,将每个算法都封装 起来,并且使它们之间可以互换。这里依旧举例来说明:假定现有需求,对于用户的各种不同行为增加不同的积分,比如用户登录一次增加5积分,用户注册增加15积分,这就是一个很典型的策略模式的场景。接下来来看类图:

策略模式

    由图中可以看到策略模式的角色分为:

  • 抽象策略角色(MemberPointProcessor),该角色为一个接口类,抽象出计算方法,所有具体策略角色都实现此接口。
  • 具体实现策略角色(MemberRegistPointProcessor等),该角色为对于抽象策略角色的具体实现。
  • 上下文(MemberPointContext)这个角色主要对外做一层封装,可不要,想比如前面说的AopProxy那块代码里其实就是没有这个角色的。

下面来看具体代码实现:

    首先抽象策略角色MemberPointProcessor:

public interface MemberPointProcessor {    /**     * 给用户增加积分     */    void addProcessor();}

    下面为具体策略实现:

public class MemberCertificationPointProcessor implements MemberPointProcessor {    public void addProcessor() {        System.out.println("用户正在执行实名认证操作,给用户增加20积分");    }}public class MemberLoginPointProcessor implements MemberPointProcessor {    public void addProcessor() {        System.out.println("用户正在执行登录操作,给用户增加5积分");    }}public class MemberRegistPointProcessor implements MemberPointProcessor {    public void addProcessor() {        System.out.println("用户正在执行注册操作,给用户增加15积分");    }}

    接下来是上下文角色:

public class MemberPointContext {    /** 策略类 */    private MemberPointProcessor memberPointProcessor;    public MemberPointContext(MemberPointProcessor memberPointProcessor) {        this.memberPointProcessor = memberPointProcessor;    }    /**     * 执行策略方法     */    public void process() {        this.memberPointProcessor.addProcessor();    }}

    最后是场景类:

public class MemberOperationService {    /**     * 给用户增加积分     */    public void addPoint(MemberBehaviorEnum memberBehavior) {        switch (memberBehavior) {            case REGIST:                new MemberPointContext(new MemberRegistPointProcessor()).process();                break;            case LOGIN:                new MemberPointContext(new MemberLoginPointProcessor()).process();                break;            case CERTIFICATION:                new MemberPointContext(new MemberCertificationPointProcessor()).process();                break;            default:                break;        }    }}//场景类中用到的枚举public enum MemberBehaviorEnum {    REGIST("注册"),    LOGIN("登录"),    CERTIFICATION("实名认证");    private String message;    MemberBehaviorEnum(String message) {        this.message = message;    }    public String getMessage() {        return message;    }}

    接下来调用方法测试:

public static void main(String[] args) {    MemberOperationService service = new MemberOperationServiceImpl();    service.addPoint(MemberBehaviorEnum.REGIST);    service.addPoint(MemberBehaviorEnum.LOGIN);    service.addPoint(MemberBehaviorEnum.CERTIFICATION);}

    执行结果:

用户正在执行注册操作,给用户增加15积分用户正在执行登录操作,给用户增加5积分用户正在执行实名认证操作,给用户增加20积分

总结:

优点:

  1. 调用者选择具体策略,可自由切换(也是缺点,下面说道),比如某天登录要涨20分了,可以直接让登录的地方选择增加20分的那个算法。
  2. 避免过多的if()…else if()…。平常我们代码中如果条件判断超过3的把,就可以考虑策略模式,使代码可读性更高。
  3. 扩展性好,比如要新增用户签到,只需增加一种策略,并且在场景类中加一个case即可,不会对原有其他逻辑造成改动。

缺点:

  1. 类数量增多,每种策略都是一个类,导致类数量很多,而且比如有的算法,过段时间过时了,又会造成算法新增
  2. 违背迪米尔法则,即上面所说的优点第一点,场景类需要很清楚的了解每个策略是干嘛的来觉得调用谁,对于场景类的知识依赖度过高

改进办法:参考AopProxy那块的实现,将策略模式和工厂模式结合使用,可解决缺点的第二条。

今天先到这里,下次给大家带来AopProxy那块源码解读。


欢迎关注个人博客:blog.scarlettbai.com

0 0