一、現在有很多關於策略模式,工廠模式和模板方法的介紹。但是基本都是main方法來展示的,不太清楚怎麼移植到自己代碼中。這裏將其中if else當很多的時候,通過這三種模式與spring結合起來。
這個是當計算商品的價格時候,通過不同會員類型來計算,應該支付的價格的僞代碼。可以看到根據三種不同類型,擁有不同折扣。其實看到這個代碼,並不算麻煩。如果這一塊經常變動,這就會導致這個算法越來越臃腫,進而得到的後果就是代碼行數越來越多,開發人員改動一點點代碼都需要把所有功能全部都回歸一遍。下面通過幾種模式的運用,將這一塊解耦開來。
public BigDecimal quotePrice(BigDecimal orderPrice, String type) {
if ("particularlyVip".equals(type)) {
return orderPrice.multiply(new BigDecimal(0.95));
}
if ("Vip".equals(type)) {
return orderPrice.multiply(new BigDecimal(0.9));
}
if ("Vip".equals(type)) {
return orderPrice.multiply(new BigDecimal(0.8));
}
return orderPrice;
}
首先定義一個service的接口,定義不同策略類。讓不同策略類實現計算價格的這一接口。
public interface UserPayService {
/**
* 計算應付價格
*/
BigDecimal quotePrice(BigDecimal orderPrice);
}
定義一個抽象模板類,實現service和InitializingBean 接口,afterPropertiesSet用於註冊到工廠方法之中。這樣剩下的策略方法只用繼承UserPayTemplate ,實現quotePrice這個方法。
public abstract class UserPayTemplate implements UserPayService,InitializingBean {
private String type;
public UserPayTemplate(String type) {
this.type = type;
}
@Override
public abstract BigDecimal quotePrice(BigDecimal orderPrice);
@Override
public void afterPropertiesSet() throws Exception {
UserPayStrategyFactory.register(type,this);
}
}
三種策略方法,繼承抽象模板類去實現具體計算應付價格的具體邏輯。
@Service
public class ParticularlyVipPayService extends UserPayTemplate {
private static final String type = "particularlyVip";
public ParticularlyVipPayService() {
super(type);
}
@Override
public BigDecimal quotePrice(BigDecimal orderPrice) {
return orderPrice.multiply(new BigDecimal(0.95));
}
}
@Service
public class SuperVipPayService extends UserPayTemplate {
private static final String type = "SuperVip";
public SuperVipPayService() {
super(type);
}
@Override
public BigDecimal quotePrice(BigDecimal orderPrice) {
return orderPrice.multiply(new BigDecimal(0.8));
}
}
@Service
public class VipPayService extends UserPayTemplate {
private static final String type = "Vip";
public VipPayService() {
super(type);
}
@Override
public BigDecimal quotePrice(BigDecimal orderPrice) {
return orderPrice.multiply(new BigDecimal(0.9));
}
}
定義一個工廠方法,讓工廠方法與不同策略結合起來。在選擇不同策略的時候,通過工廠類來創造這個方法。
public class UserPayStrategyFactory {
private static Map<String,UserPayService> services = new ConcurrentHashMap<String,UserPayService>();
public static UserPayService getByUserType(String type){
return services.get(type);
}
public static void register(String userType,UserPayService userPayService){
Assert.notNull(userType,"type can't be null");
services.put(userType,userPayService);
}
}
下面是Controller的測試方法,通過這種將數據庫裏面的數據和剛剛定義的不同策略結合起來,並查看測試結果。
@PostMapping("/getRequest")
public String testRequestBody(HttpServletRequest request, HttpServletResponse response) throws IOException {
String type1 = "particularlyVip";
UserPayService userPayService = UserPayStrategyFactory.getByUserType(type1);
BigDecimal quote = userPayService.quotePrice(new BigDecimal(300));
System.out.println("particularlyVip會員商品的最終價格爲:" + quote.doubleValue());
String type2 = "Vip";
UserPayService userPayService2 = UserPayStrategyFactory.getByUserType(type2);
BigDecimal quote2 = userPayService2.quotePrice(new BigDecimal(300));
System.out.println("vip會員商品的最終價格爲:" + quote2.doubleValue());
String type3= "SuperVip";
UserPayService userPayService3 = UserPayStrategyFactory.getByUserType(type3);
BigDecimal quote3 = userPayService3.quotePrice(new BigDecimal(300));
System.out.println("SuperVip會員商品的最終價格爲:" + quote3.doubleValue());
return "success";
}
測試結果:
particularlyVip會員商品的最終價格爲:285.0
vip會員商品的最終價格爲:270.0
SuperVip會員商品的最終價格爲:240.0