若是你們對策略模式和工廠模式不是很瞭解的話能夠先看前面文章
策略模式:https://www.jianshu.com/p/958281936901
工廠模式:https://www.jianshu.com/p/9078481e00c6java
一、當咱們的付款金額大於咱們的餘額時,會讓咱們使用銀行卡支付,
二、餘額充足的時候會讓咱們優先使用餘額裏面的錢
扣款策略一:
餘額(blance) >= 付款金額(tradeAmout) 使用餘額
扣款策略二:
餘額(blance) < 付款金額(tradeAmout) 使用銀行卡
很明顯這是一個策略模式的實際應用,可是你還記得策略模式的缺陷嗎?它的具體策略必須暴露出去,並且還要由上層模塊初始化,這不適合,與迪米特法則不符( 迪米特法則(Law of Demeter)又叫做最少知識原則(Least Knowledge Principle 簡寫LKP),就是說一個對象應當對其餘對象有儘量少的瞭解,不和陌生人說話。注:摘自百度百科,這個迪米特法則下次再細講)衝突。高層模塊對底層模塊僅僅在接觸層次上,而不該該是耦合關係。問題出了,咱們應該想辦法解決,正好工廠模式能夠幫咱們解決這個問題。可是引入工廠模式也有問題,工廠方法要指定一個類,它才能生產對象,咱們用枚舉來完成。
首先咱們先建兩個實體類WxBlance和WxTrade微信
import java.math.BigDecimal; /** * @author shuliangzhao * @Title: WxBlance * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:50 */ public class WxBlance { //餘額 private BigDecimal blance; public BigDecimal getBlance() { return blance; } public void setBlance(BigDecimal blance) { this.blance = blance; } }
import java.math.BigDecimal; /** * @author shuliangzhao * @Title: Trade * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:51 */ public class WxTrade { private BigDecimal tradeAmout; private String tradeNo; private BigDecimal userAmout; public BigDecimal getUserAmout() { return userAmout; } public void setUserAmout(BigDecimal userAmout) { this.userAmout = userAmout; } public String getTradeNo() { return tradeNo; } public void setTradeNo(String tradeNo) { this.tradeNo = tradeNo; } public BigDecimal getTradeAmout() { return tradeAmout; } public void setTradeAmout(BigDecimal tradeAmout) { this.tradeAmout = tradeAmout; } }
扣款策略接口ide
/** * @author shuliangzhao * @Title: Deduction * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:53 */ public interface Deduction { public boolean exec(WxBlance wxBlance,WxTrade wxTrade); }
扣款策略一微信支付
/** * @author shuliangzhao * @Title: BlanceDeduction * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:54 */ public class BlanceDeduction implements Deduction { @Override public boolean exec(WxBlance wxBlance, WxTrade wxTrade) { if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) >= 0) { wxTrade.setUserAmout(wxBlance.getBlance()); } return true; } }
扣款策略二this
/** * @author shuliangzhao * @Title: IdCardDeduction * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:54 */ public class IdCardDeduction implements Deduction { @Override public boolean exec(WxBlance wxBlance, WxTrade wxTrade) { if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) < 0) { wxTrade.setUserAmout(wxTrade.getTradeAmout()); } return true; } }
扣款策略封裝spa
/** * @author shuliangzhao * @Title: DedutionContext * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:58 */ public class DedutionContext { private Deduction deduction; public DedutionContext(Deduction deduction) { this.deduction = deduction; } public boolean exec(WxBlance wxBlance,WxTrade wxTrade) { return deduction.exec(wxBlance,wxTrade); } }
典型的策略上下文。策略模式的缺陷把全部策略類都暴露出去,怎麼修改呢?使用工廠模式根據映射產生策略對象code
策略枚舉對象
/** * @author shuliangzhao * @Title: StrategyEnum * @ProjectName design-parent * @Description: TODO * @date 2019/5/29 0:00 */ public enum StrategyEnum { BlanceDeduction("com.sl.factorystrategy.BlanceDeduction"), IdCardDeduction("com.sl.factorystrategy.IdCardDeduction"); String value = ""; private StrategyEnum(String value) { this.value = value; } public String getValue() { return value; } }
策略工廠接口
/** * @author shuliangzhao * @Title: StrategyFactory * @ProjectName design-parent * @Description: TODO * @date 2019/5/29 0:03 */ public class StrategyFactory { public static Deduction getDeduction(StrategyEnum strategyEnum) { Deduction deduction = null; try { deduction = (Deduction)Class.forName(strategyEnum.getValue()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return deduction; } }
扣款調用類ip
/** * @author shuliangzhao * @Title: DeductionFacade * @ProjectName design-parent * @Description: TODO * @date 2019/5/29 0:06 */ public class DeductionFacade { //扣款 public static void deduct(WxBlance wxBlance,WxTrade wxTrade) { StrategyEnum strate = getStrate(wxBlance, wxTrade); Deduction deduction = StrategyFactory.getDeduction(strate); deduction.exec(wxBlance,wxTrade); } //獲取扣款策略 private static StrategyEnum getStrate(WxBlance wxBlance,WxTrade wxTrade) { if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) < 0) { return StrategyEnum.IdCardDeduction; }else { return StrategyEnum.BlanceDeduction; } } }
調用客戶端client
/** * @author shuliangzhao * @Title: Client * @ProjectName design-parent * @Description: TODO * @date 2019/5/29 0:10 */ public class Client { public static void main(String[] args) { WxTrade wxTrade = new WxTrade(); wxTrade.setTradeAmout(new BigDecimal("1000")); WxBlance wxBlance = new WxBlance(); wxBlance.setBlance(new BigDecimal("999")); DeductionFacade.deduct(wxBlance,wxTrade); System.out.println(wxTrade.getUserAmout()); } }
執行結果
小結:
策略模式:負責對扣款封裝,保證兩個策略自由切換,之後增長策略也很容易
工廠模式:修正策略模式必須對外暴露問題,由工廠模式產生一個具體策略對象