学习笔记-----策略模式

什么是策略模式

顾名思义,针对不同的情况而提供的不同解决方案的集合,即为策略。那么此模式则是为了针对不同情况提供不同的算法,根据情况使用不同的算法进行计算。

生活中的策略模式

  • 诸葛亮的锦囊妙计

  • 旅行前选择出行方式(汽车,飞机,货车)

  • 购买电脑时商家提供的不同的配置方案

举个栗子

项目一期

公司开发了一个商城APP,由于考虑项目初期使用人员不多,

项目前期只提供三个级别会员,分别是:

  • 普通会员,
  • 金牌会员,
  • 钻石会员

不同级别的会员在购买商品后可以提供不同的打折方案,方案如下:

  • 普通会员:原价的9.9折
  • 金牌会员:原价的9.5折
  • 钻石会员:原价的9折

我们的开发人员小王在拿到需求后直接上手就干,并且很快就开发完此功能,代码如下:

会员对象
@Getter
@Setter
public class Member {
   private MemberLevelEnum level;
   private String name;
}
会员等级枚举
public enum MemberLevelEnum {
	//普通会员
    GENERAL,
    //金牌会员
    GOLD,
    //钻石会员
    DIAMONDS
}
价格打折方案
public class PriceCalculation {
    public static Double calculation(Double price, Member member) throws Exception {
        if(MemberLevelEnum.GENERAL.equals(member.getLevel()) ){
            price *= 0.95;
        }else if(MemberLevelEnum.GOLD.equals(member.getLevel())){
            price *= 0.9;
        }else if(MemberLevelEnum.DIAMONDS.equals(member.getLevel())){
            price *= 0.8;
        }else{
            throw new Exception("无此会员级别");
        }
        return price;
    }
}
    }

项目二期

随着一期产品的成功,会员数量大幅上升,为了更加细化用户级别,提供更好的服务,获取更加优质的顾客,决定增加更高的用户级别,提供更高的折扣方案,方案如下

增加用户级别:超级会员

用户级别折扣:钻石会员的基础上再打9折

开发人员小王在拿到方案后,觉得很轻松,只要为用户等级枚举增加一个等级, 并且在打折方案中增加一个判断即可,说干就干,开发快被完成,代码如下:

会员级别
public enum MemberLevelEnum {
    GENERAL,
    GOLD,
    DIAMONDS,
    SUPER
}
打折方案
public class PriceCalculation {
    public static Double calculation(Double price, Member member) throws Exception {
        if(MemberLevelEnum.GENERAL.equals(member.getLevel()) ){
            price *= 0.95;
        }else if(MemberLevelEnum.GOLD.equals(member.getLevel())){
            price *= 0.9;
        }else if(MemberLevelEnum.DIAMONDS.equals(member.getLevel())){
            price *= 0.8;
        }else if(MemberLevelEnum.SUPER.equals(member.getLevel())){
            price = price*0.8*0.9;
        }else{
            throw new Exception("无此会员级别");
        }
        return price;
    }
}
打折方案升级版

可是在此时小王突然想到,如果钻石会员的折扣变了,那岂不是需要改两个地方的算法?如果是一个不知道业务的新人修改那岂不是要出大事,于是小王将折扣算法提取成方法,开发出了打折方案的升级版,代码如下

/**
     * 打折
     * [@param](https://my.oschina.net/u/2303379) price
     *            商品合计价格
     * [@param](https://my.oschina.net/u/2303379) member
     *            会员实例
     * [@return](https://my.oschina.net/u/556800) 打折后价格
     * [@throws](https://my.oschina.net/throws) Exception
     */
    public static Double calculation(Double price, Member member) throws Exception {
        if(MemberLevelEnum.GENERAL.equals(member.getLevel()) ){
            return calculateGeneral(price);
        }else if(MemberLevelEnum.GOLD.equals(member.getLevel())){
            return calculateGold(price);
        }else if(MemberLevelEnum.DIAMONDS.equals(member.getLevel())){
            return calculateDiamonds(price);
        }else if(MemberLevelEnum.SUPER.equals(member.getLevel())){
            return calculateSuper(price);
        }else{
            throw new Exception("无此会员级别");
        }
    }

    /**
     * 普通会员打折方案
     * [@param](https://my.oschina.net/u/2303379) price
     *           价格
     * @return  折后价格
     */
    private static Double calculateGeneral(Double price){
        return price*0.99;
    }
    /**
     * 金牌会员打折方案
     * @param price
     *           价格
     * @return  折后价格
     */
    private static Double calculateGold(Double price){
        return price*0.95;
    }
    /**
     * 钻石会员打折方案
     * @param price
     *           价格
     * @return  折后价格
     */
    private static Double calculateDiamonds(Double price){
        return price*0.9;
    }
    /**
     * 超级会员打折方案
     * @param price
     *           价格
     * @return  折后价格
     */
    private static Double calculateSuper(Double price){
        return calculateDiamonds(price)*0.9;
    }
}

最终项目优化

项目的老司机小李在做代码的审核时,发现此处代码存在问题,如果某个方法出错,则会导致整个会员打折功能无法使用,从而造成项目的事故。所以老司机为此做出了代码的优化方案,方案如下:

  1. 将项目中的会员打折方案提取,并抽象。
  2. 不同的会员级别分别实现此抽象类,使用对应会员级别的算法,来实现同一个折算方案

具体代码如下:

抽象策略
public interface PriceCalculationStrategy {
    Double calculate(Double price);
}
各具体实现策略

普通会员打折实现类

/**
 * 普通会员打折实现类
 * Created by asus on 2018/4/12.
 */
public class GeneralPriceCalculationStrategy implements PriceCalculationStrategy{
    @Override
    public Double calculate(Double price){
        return price*0.95;
    }
}

金牌会员打折实现类

/**
 * 金牌会员打折实现类
 * Created by asus on 2018/4/12.
 */
public class GoldPriceCalculationStrategy implements PriceCalculationStrategy{
    @Override
    public Double calculate(Double price){
        return price*0.9;
    }
}

钻石会员打折实现类

/**
 * 钻石会员打折实现类
 * Created by asus on 2018/4/12.
 */
public class DiamodsPriceCalculationStrategy implements PriceCalculationStrategy{
    @Override
    public Double calculate(Double price){
        return price*0.8;
    }
}

超级会员打折实现类

/**
 * 超级会员打折实现类
 * Created by asus on 2018/4/12.
 */
public class SuperPriceCalculationStrategy implements PriceCalculationStrategy{
    @Override
    public Double calculate(Double price){
        return new PriceCalculationDiamods().calculate(price)*0.9;
    }
}
环境(context)
public class MemberPay {
    private PriceCalculationStrategy priceCalculation = null;

    /**
     * 实例化 传入具体会员折算策略
     * @param priceCalculation
     */
    public MemberPay(PriceCalculationStrategy priceCalculation) {
        this.priceCalculation = priceCalculation;
    }

    public Double calculate(Double price) {
        return priceCalculation.calculate(price);
    }
}
优点
  • 面向接口编程扩展性好
  • 多个算法中间可以自由切换
  • 避免使用多重判断
缺点

策略类会增加很多

元素

环境(Context)角色:持有一个Strategy的引用。

抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

特点

别管我怎么工作,达到目的就行

转载于:https://my.oschina.net/u/3518687/blog/1796469

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值