用户多种会员的价格优惠不一样,正常的代码实现 if
public static BigDecimal calPrice(BigDecimal orderPrice,String buyerType){
if("svip".equals(buyerType)){
if(orderPrice.compareTo(BigDecimal.valueOf(28))>0){
return orderPrice.multiply(BigDecimal.valueOf(0.8));
}
}
if("vip".equals(buyerType)){
return orderPrice.multiply(BigDecimal.valueOf(0.9));
}
if("ssvip".equals(buyerType)){
return orderPrice.multiply(BigDecimal.valueOf(0.7));
}
return orderPrice;
}
客户端调用
public static void main(String[] args) {
calPrice(BigDecimal.valueOf(200),"svip");
}
这样的话,如果新增一种会员,则 calPrice 方法就得做调整,违背了开闭原则,而且逻辑结构与算法过于耦合。
接下来就是策略模式出场了,先看下定义,策略模式:指的是定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。
1、定义计算价格的接口,具体实现方法由具体的策略类来定义
public interface Buyer {
/**
* 计算价格
* @param orderPrice
* @return
*/
BigDecimal calPrice(BigDecimal orderPrice);
}
2、具体的策略类
public class SSvipBuyer implements Buyer {
@Override
public BigDecimal calPrice(BigDecimal orderPrice) {
return orderPrice.multiply(BigDecimal.valueOf(0.7));
}
}
public class SvipBuyer implements Buyer {
@Override
public BigDecimal calPrice(BigDecimal orderPrice) {
return orderPrice.multiply(BigDecimal.valueOf(0.8));
}
}
public class VipBuyer implements Buyer {
@Override
public BigDecimal calPrice(BigDecimal orderPrice) {
return orderPrice.multiply(BigDecimal.valueOf(0.9));
}
}
3、上下文类(就是集成算法的类)
public class Cashiler {
private Buyer buyer;
public Cashiler(Buyer buyer){
this.buyer = buyer;
}
public BigDecimal quota(BigDecimal orderPrice){
return buyer.calPrice(orderPrice);
}
}
4、客户端调用
public class SimpleCalPrice {
public static void main(String[] args) {
//不使用上下文调用
Buyer buyer = new SSvipBuyer();
BigDecimal price = buyer.calPrice(BigDecimal.valueOf(100));
System.out.println(price);
//使用上下文调用
Cashiler cashiler = new Cashiler(new SvipBuyer());
BigDecimal quota = cashiler.quota(BigDecimal.valueOf(100));
System.out.println(quota);
}
到这里,可能大家就有疑问了,这边用上下文调用和直接调用策略接口的方式好像没什么不同,那么这个上下文有什么作用呢?
试想一下,如果每个具体的策略都有一个需要执行的代码,例如 System.out.println("每个策略类都需要执行的代码"),这样你需要再每个策略类添加这个代码,
如果有上下文这个类,你可以把公用的代码写在该类中
public class Cashiler {
private Buyer buyer;
public Cashiler(Buyer buyer){
this.buyer = buyer;
}
public BigDecimal quota(BigDecimal orderPrice){
System.out.println("每个策略类都需要执行的代码");
return buyer.calPrice(orderPrice);
}
}
在实际开发中,我们的需求往往不会像结构示意图那样,如此简单、如此simple。实际较为常见的情况就是:上层的调用需要与接口之间有一定的交互。交互的可能是一些属性,或是一些方法。这样的交互往往会让接口变的难以调用;于是上下文的引入就是势在必行。将相关的属性或一些公共的方法封装到上下文中,让上下文去和接口进行复杂的交互。而上层的调用只需要跟上下文打交道就可以。
策略模式仅仅封装算法,提供新的算法插入到已有系统中,策略模式并不决定在何时使用何种算法。在什么情况下使用什么算法是由客户端决定的。