14.(行为型模式)java设计模式之策略模式

一、什么是策略模式

    策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

  • 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。
  • 淘宝天猫双十一,正在搞活动有打折的、有满减的、有返利的等等,这些算法只是一种策略,并且是随时都可能互相替换的,我们就可以定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。

二、策略模式的实现方式

模式结构分析:

  • Context上下文:屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化
  • Strategy策略角色∶抽象策略角色,是对策略、算法家族的抽象,定义每个策略或算法必须具有的方法和属性
  • ConcreteStrategy具体策略角色:用于实现抽象策略中的操作,即实现具体的算法

类关系图:

统一模型:

代码实现:

查看代码

/*
*  具体的商品信息
* */
@Data
public class ProductOrder {
    private double oldPrice;
    private int userId;
    private int productId;
    public ProductOrder(double oldPrice, int userId, int productId){
        this.oldPrice = oldPrice;
        this.userId = userId;
        this.productId = productId;
    }
}
/*
* 需要计算价格的一个策略
* */
public abstract class Strategy {
    public abstract double computePrice(ProductOrder productOrder);
}
public class NormalActivity extends  Strategy {
    @Override
    public double computePrice(ProductOrder productOrder) {
        return productOrder.getOldPrice();
    }
}
/*
* 进行折扣
* */
public class DiscountActivity extends Strategy {
    /**
     * 具体的折扣
     */
    private double rate;
    public DiscountActivity(double rate){
        this.rate = rate;
    }
    @Override
    public double computePrice(ProductOrder productOrder) {
        return productOrder.getOldPrice()*rate;
    }
}
/*
* 传⼊优惠券
* */
public class CouponActivity extends  Strategy{
    private double couponPrice;
    public  CouponActivity(double couponPrice){
        this.couponPrice = couponPrice;
    }
    @Override
    public double computePrice(ProductOrder productOrder) {
        if(productOrder.getOldPrice()>couponPrice){
            return productOrder.getOldPrice()-couponPrice;
        }else{
            return 0;
        }
    }
}
/*
* 使用中这种策略的上下文
* */
public class PromotionContext {
    private Strategy strategy;
    public  PromotionContext(Strategy strategy){
        this.strategy = strategy;
    }
    /**
     * 根据策略计算最终的价格
     * @param productOrder
     * @return
     */
    public double executeStrategy(ProductOrder productOrder){
        return strategy.computePrice(productOrder);
    }
}

测试用例:

/*
 * 策略模式
 * */
@Test
public void strategy() {
    ProductOrder productOrder = new ProductOrder(800, 1, 32);
    PromotionContext context;
    double finalPrice;
    //没活动
    context = new PromotionContext(new NormalActivity());
    finalPrice = context.executeStrategy(productOrder);
    System.out.println("NormalActivity =" + finalPrice);
    //折扣策略
    context = new PromotionContext(new DiscountActivity(0.8));
    finalPrice = context.executeStrategy(productOrder);
    System.out.println("DiscountActivity =" + finalPrice);
    //优惠券抵扣
    context = new PromotionContext(new CouponActivity(100));
    finalPrice = context.executeStrategy(productOrder);
    System.out.println("VoucherActivity ="+finalPrice);
}

测试结果:

NormalActivity =800.0
DiscountActivity =640.0
VoucherActivity =700.0

方法评估:

优点:

  • 满足开闭原则,当增加新的具体策略时,不需要修改上下文类的代码,上下文就可以引用新的具体策略的实例。
  • 避免使用多重条件判断,如果不用策略模式可能会使用多重条件语句不利于维护,和工厂模式的搭配使用可以很好地消除代码if-else的多层嵌套(工厂模式主要是根据参数,获取不同的策略)。

缺点:

  • 策略类数量会增多,每个策略都是一个类,复用的可能性很小
  • 对外暴露了类所有的行为和算法,行为过多导致策略类膨胀
posted @ 2023-01-16 20:24  冰融心  阅读(29)  评论(0编辑  收藏  举报