您好,登錄后才能下訂單哦!
本篇內容介紹了“Java怎么優雅的使用策略模式”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
策略模式是一種行為型模式,它將對象和行為分開,將行為定義為 一個行為接口 和 具體行為的實現。策略模式最大的特點是行為的變化,行為之間可以相互替換。每個if判斷都可以理解為就是一個策略。本模式使得算法可獨立于使用它的用戶而變化。
簡單理解就是,針對不同的場景,使用不同的策略進行處理。
Strategy 接口定義了一個算法族,它們都實現了 behavior() 方法。
Context 是使用到該算法族的類,其中的 doSomething() 方法會調用 behavior(),setStrategy(Strategy) 方法可以動態地改變 strategy 對象,也就是說能動態地改變 Context 所使用的算法。
如果在一個系統里面有許多類,它們之間的區別僅在于它們 的行為,那么使用策略模式可以動態地讓一個對象在許多行 為中選擇一種行為。
一個系統需要動態地在幾種算法中選擇一種。
如果一個對象有很多的行為,如果不用恰當的模式,這些行 為就只好使用多重的條件選擇語句來實現。
不希望客戶端知道復雜的、與算法相關的數據結構,在具體策略類中封裝算法和相關的數據結構,提高算法的保密性與安全性。
生活中比較常見的應用模式有:
電商網站支付方式,一般分為銀聯、微信、支付寶,可以采用策略模式。
電商網站活動方式,一般分為滿減送、限時折扣、包郵活動,拼團等可以采用策略模式。
場景:最近太熱了,想要降降溫,有什么辦法呢
首先,定義一個降溫策略的接口
public interface CoolingStrategy { /** * 處理方式 */ void handle(); }
定義3種降溫策略;實現策略接口
public class IceCoolingStrategy implements CoolingStrategy { @Override public void handle() { System.out.println("使用冰塊降溫"); } }
public class FanCoolingStrategy implements CoolingStrategy { @Override public void handle() { System.out.println("使用風扇降溫"); } }
public class AirConditionerCoolingStrategy implements CoolingStrategy { @Override public void handle() { System.out.println("使用空調降溫"); } }
定義一個降溫策略的上下文
public class CoolingStrategyContext { private final CoolingStrategy strategy; public CoolingStrategyContext(CoolingStrategy strategy) { this.strategy = strategy; } public void coolingHandle() { strategy.handle(); } }
測試
public class Main { public static void main(String[] args) { CoolingStrategyContext context = new CoolingStrategyContext(new FanCoolingStrategy()); context.coolingHandle(); context = new CoolingStrategyContext(new AirConditionerCoolingStrategy()); context.coolingHandle(); context = new CoolingStrategyContext(new IceCoolingStrategy()); context.coolingHandle(); } }
運行結果:
使用風扇降溫
使用空調降溫
使用冰塊降溫
以上就是一個策略模式的簡單實現
模擬在購買商品時候使用的各種類型優惠券(滿減、直減、折扣、n元購)
這個場景幾乎也是大家的一個日常購物省錢渠道,購買商品的時候都希望找一些優惠券,讓購買的商品更加實惠。而且到了大促的時候就會有更多的優惠券需要計算那些商品一起購買更加優惠!
/** * 優惠券折扣計算接口 * <p> * 優惠券類型; * 1. 直減券 * 2. 滿減券 * 3. 折扣券 * 4. n元購 */ public class CouponDiscountService { public double discountAmount(int type, double typeContent, double skuPrice, double typeExt) { // 1. 直減券 if (1 == type) { return skuPrice - typeContent; } // 2. 滿減券 if (2 == type) { if (skuPrice < typeExt) return skuPrice; return skuPrice - typeContent; } // 3. 折扣券 if (3 == type) { return skuPrice * typeContent; } // 4. n元購 if (4 == type) { return typeContent; } return 0D; } }
以上是不同類型的優惠券計算折扣后的實際金額。
入參包括;優惠券類型、優惠券金額、商品金額,因為有些優惠券是滿多少減少多少,所以增加了typeExt
類型。這也是方法的不好擴展性問題。
最后是整個的方法體中對優惠券抵扣金額的實現,最開始可能是一個最簡單的優惠券,后面隨著產品功能的增加,不斷的擴展if
語句。實際的代碼可能要比這個多很多
整體的結構模式并不復雜,主要體現的不同類型的優惠券在計算優惠券方式的不同計算策略。
這里包括一個接口類(ICouponDiscount
)以及四種優惠券類型的實現方式。
最后提供了策略模式的上下控制類處理,整體的策略服務。
優惠券接口
public interface ICouponDiscount<T> { /** * 優惠券金額計算 * @param couponInfo 券折扣信息;直減、滿減、折扣、N元購 * @param skuPrice sku金額 * @return 優惠后金額 */ BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice); }
定義了優惠券折扣接口,也增加了泛型用于不同類型的接口可以傳遞不同的類型參數。
接口中包括商品金額以及出參返回最終折扣后的金額,這里在實際開發中會比現在的接口參數多一些,但核心邏輯是這些。
優惠券接口實現
滿減
public class MJCouponDiscount implements ICouponDiscount<Map<String,String>> { /** * 滿減計算 * 1. 判斷滿足x元后-n元,否則不減 * 2. 最低支付金額1元 */ public BigDecimal discountAmount(Map<String,String> couponInfo, BigDecimal skuPrice) { String x = couponInfo.get("x"); String o = couponInfo.get("n"); // 小于商品金額條件的,直接返回商品原價 if (skuPrice.compareTo(new BigDecimal(x)) < 0) return skuPrice; // 減去優惠金額判斷 BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(o)); if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE; return discountAmount; } }
直減
public class ZJCouponDiscount implements ICouponDiscount<Double> { /** * 直減計算 * 1. 使用商品價格減去優惠價格 * 2. 最低支付金額1元 */ public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) { BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(couponInfo)); if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE; return discountAmount; } }
折扣
public class ZKCouponDiscount implements ICouponDiscount<Double> { /** * 折扣計算 * 1. 使用商品價格乘以折扣比例,為最后支付金額 * 2. 保留兩位小數 * 3. 最低支付金額1元 */ public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) { BigDecimal discountAmount = skuPrice.multiply(new BigDecimal(couponInfo)).setScale(2, BigDecimal.ROUND_HALF_UP); if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE; return discountAmount; } }
N元購
public class NYGCouponDiscount implements ICouponDiscount<Double> { /** * n元購購買 * 1. 無論原價多少錢都固定金額購買 */ public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) { return new BigDecimal(couponInfo); } }
以上是四種不同類型的優惠券計算折扣金額的策略方式,可以從代碼中看到每一種優惠方式的優惠金額。
策略控制類
public class Context<T> { private ICouponDiscount<T> couponDiscount; public Context(ICouponDiscount<T> couponDiscount) { this.couponDiscount = couponDiscount; } public BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice) { return couponDiscount.discountAmount(couponInfo, skuPrice); } }
策略模式的控制類主要是外部可以傳遞不同的策略實現,在通過統一的方法執行優惠策略計算。
另外這里也可以包裝成map結構,讓外部只需要對應的泛型類型即可使用相應的服務。
測試類
public class ApiTest { private Logger logger = LoggerFactory.getLogger(ApiTest.class); @Test public void test_zj() { // 直減;100-10,商品100元 Context<Double> context = new Context<Double>(new ZJCouponDiscount()); BigDecimal discountAmount = context.discountAmount(10D, new BigDecimal(100)); logger.info("測試結果:直減優惠后金額 {}", discountAmount); } @Test public void test_mj() { // 滿100減10,商品100元 Context<Map<String,String>> context = new Context<Map<String,String>>(new MJCouponDiscount()); Map<String,String> mapReq = new HashMap<String, String>(); mapReq.put("x","100"); mapReq.put("n","10"); BigDecimal discountAmount = context.discountAmount(mapReq, new BigDecimal(100)); logger.info("測試結果:滿減優惠后金額 {}", discountAmount); } @Test public void test_zk() { // 折扣9折,商品100元 Context<Double> context = new Context<Double>(new ZKCouponDiscount()); BigDecimal discountAmount = context.discountAmount(0.9D, new BigDecimal(100)); logger.info("測試結果:折扣9折后金額 {}", discountAmount); } @Test public void test_nyg() { // n元購;100-10,商品100元 Context<Double> context = new Context<Double>(new NYGCouponDiscount()); BigDecimal discountAmount = context.discountAmount(90D, new BigDecimal(100)); logger.info("測試結果:n元購優惠后金額 {}", discountAmount); } }
以上四組測試分別驗證了不同類型優惠券的優惠策略,測試結果是滿足我們的預期。
這里四種優惠券最終都是在原價100元上折扣10元,最終支付90元。
“Java怎么優雅的使用策略模式”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。