【设计模式】策略模式

策略模式是一种很常用的模式,尽管他有一些缺点,但是在我们日常代码中依旧经常用到,另外大家可以看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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值