设计模式--行为型--策略模式

策略模式的使用场景,利用策略模式来避免冗长的if-else或者switch分支判断。还可以像模板模式那样,提供框架的扩展点等等。

 

策略模式,英文名Strategy Design  Pattern。定义一族算法类,将每个算法类封装起来,让它们可以相互替换。策略模式可以使算法类的变化独立于使用它们的客户端。(客户端指的是调用者)

 

策略模式用来解耦策略的定义、创建和使用。实际上一个完整策略模式就是由这三部分组成起来的。

1、策略的定义

策略类的定义比较简单,包含一个接口和一组实现这个接口的策略类。

 

2、策略的创建

策略的创建由工厂类来完成,封装策略的创建方式。这里需要分两种情况

a、如果策略类是无状态的,不包含成员变量,只是纯粹的算法实现,这样的策略对象是可以被共享使用的,不需要每次获取策略对象的时候都创建一个新的对象。针对这种情况,我们可以事先创建好每个策略对象,缓存到工厂类中,用的时候直接返回

b、如果策略类有状态,根据业务场景的需求,希望每次都返回一个新的对象。针对这种情况,每次使用的时候都返回一个新创建的策略对象。

 

3、策略的使用

策略模式包含一组可选策略,客户端代码如何来使用这些策略中的哪一个,有两种确定方法:编译时静态确认和运行时动态确认。其中“运行时动态确认”才是策略模式最典型的应用场景。

 

策略模式如何移除if-else分支判断?

举个栗子,代码示例如下。根据订单类型来计算商品的折扣。使用的if-else,将策略的定义、创建以及使用直接耦合再一起。

/**
 * 订单处理类
 */
public class OrderService {

    public double discount(Order order){
        double disount=0.0;
        String orderType=order.getType();
        if(orderType.equals(OrderTypeEnum.NORMAL.getType())){  //普通订单
            // ...省略折扣计算算法
        }else if(orderType.equals(OrderTypeEnum.GROUPON.getType())){ //团购订单
            // ...省略折扣计算算法
        }else if(orderType.equals(OrderTypeEnum.PROMOTION.getType())){ //促销订单
            // ...省略折扣计算算法
        }

        return disount;
    }
}

那如何使用策略模式移除if-else呢?将策略的定义、策略的创建以及策略的使用分离呢?

1、策略定义

/**
 * 折扣策略接口
 */
public interface DiscountStrategy {
    //计算折扣
    double calDiscount();
}

public class NomalDiscountStrategy implements DiscountStrategy {
    @Override
    public double calDiscount() {
        //..省略计算折扣的实现代码
    }
}

public class GrouponDiscountStrategy implements DiscountStrategy {
    @Override
    public double calDiscount() {
        //..省略计算折扣的实现代码
    }
}

public class PromotionDiscountStrategy implements DiscountStrategy {
    @Override
    public double calDiscount() {
        //..省略计算折扣的实现代码
    }
}

2、策略创建

a、策略类无状态,策略创建代码如下

/**
 * 策略类无状态,策略工厂
 */
public class DiscountStrategyFactory {
    public static final Map<String,DiscountStrategy> strategys=new HashMap<>();

    static {
        map.put(OrderTypeEnum.NORMAL.getType(),new NomalDiscountStrategy());
        map.put(OrderTypeEnum.GROUPON.getType(),new GrouponDiscountStrategy());
        map.put(OrderTypeEnum.PROMOTION.getType(),new PromotionDiscountStrategy());
    }

    public static DiscountStrategy getInstance(String orderType){
        return map.get(orderType);
    }
}

b、策略类有状态,策略创建代码如下

/**
 * 策略类有状态,策略工厂
 */
public class DiscountStrategyFactory {
    public static DiscountStrategy getInstance(String orderType){
        if(orderType.equals(OrderTypeEnum.NORMAL.getType())){  //普通订单
            return new NomalDiscountStrategy();
        }else if(orderType.equals(OrderTypeEnum.GROUPON.getType())){ //团购订单
            return new GrouponDiscountStrategy();
        }else if(orderType.equals(OrderTypeEnum.PROMOTION.getType())){ //促销订单
            return new PromotionDiscountStrategy();
        }
        return null;
    }
}

3、策略使用

重构OrderService,代码如下:

/**
 * 订单处理类
 */
public class OrderService {

    public double discount(Order order){
        double disount=0.0;
        String orderType=order.getType();
        disount= DiscountStrategyFactory.getInstance(orderType).calDiscount();
        return disount;
    }
}

类图如下

 

参考:设计模式之美--王争

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值