做者:小傅哥
博客:https://bugstack.cn - 原創系列專題文章
html
沉澱、分享、成長,讓本身和他人都能有所收穫!😄
文無第一,武無第二
java
不一樣方向但一樣努力的人,都有自身的價值和亮點,也都是能夠互相學習的。不要太過於用本身手裏的矛去攻擊別人的盾🛡,哪怕一時爭辯過了也多半多是你被安放的角色不一樣。取別人之強補本身之弱,矛與盾的結合可能就是坦克。程序員
能把複雜的知識講的簡單很重要
算法
在學習的過程當中咱們看過不少資料、視頻、文檔等,由於如今資料視頻都較多因此每每一個知識點會有多種多樣的視頻形式講解。除了推廣營銷之外,確實有不少人的視頻講解很是優秀,例如李永樂老師的短視頻課,能夠在一個黑板上把那麼複雜的知識,講解的那麼容易理解,那麼透徹。而咱們學習編程的人也是,不僅是要學會把知識點講明白,也要寫明白。編程
🙉提高本身的眼界交往更多同好
設計模式
有時候圈子很重要,就像上學期間你們都會發現班裏有這樣一類學生👩🎓不怎麼聽課,可是就是學習好。那假如讓他回家呆着,不能在課堂裏呢?相似的圈子還有;圖書館、網吧、車友羣、技術羣等等,均可以給你帶來同類愛好的人所分享出來的技能或者你們一塊兒烘托出的氛圍幫你成長。微信
bugstack蟲洞棧
,回覆源碼下載
獲取(打開獲取的連接,找到序號18)工程 | 描述 |
---|---|
itstack-demo-design-20-01 | 使用一坨代碼實現業務需求 |
itstack-demo-design-20-02 | 經過設計模式優化改造代碼,產生對比性從而學習 |
策略模式是一種行爲模式,也是替代大量ifelse
的利器。它所能幫你解決的是場景,通常是具備同類可替代的行爲邏輯算法場景。好比;不一樣類型的交易方式(信用卡、支付寶、微信)、生成惟一ID策略(UUID、DB自增、DB+Redis、雪花算法、Leaf算法)等,均可以使用策略模式進行行爲包裝,供給外部使用。學習
策略模式也有點像三國演義中諸葛亮給劉關張的錦囊;測試
在本案例中咱們模擬在購買商品時候使用的各類類型優惠券(滿減、直減、折扣、n元購)優化
這個場景幾乎也是你們的一個平常購物省錢渠道,購買商品的時候都但願找一些優惠券,讓購買的商品更加實惠。並且到了大促的時候就會有更多的優惠券須要計算那些商品一塊兒購買更加優惠!!!
這樣的場景有時候用戶用起來仍是蠻爽的,可是最初這樣功能的設定以及產品的不斷迭代,對於程序員👨💻開發仍是不太容易的。由於這裏包括了不少的規則和優惠邏輯,因此咱們模擬其中的一個計算優惠的方式,使用策略模式來實現。
這裏咱們先使用最粗暴的方式來實現功能
對於優惠券的設計最初可能很是簡單,就是一個金額的抵扣,也沒有如今這麼多種類型。因此若是沒有這樣場景的經驗話,每每設計上也是很是簡單的。但隨着產品功能的不斷迭代,若是程序最初設計的不具有很好的擴展性,那麼日後就會愈來愈混亂。
itstack-demo-design-20-01 └── src └── main └── java └── org.itstack.demo.design └── CouponDiscountService.java
一坨坨
工程的結構很簡單,也是最直接的面向過程開發方式。/** * 博客:https://bugstack.cn - 沉澱、分享、成長,讓本身和他人都能有所收穫! * 公衆號:bugstack蟲洞棧 * Create by 小傅哥(fustack) @2020 * 優惠券折扣計算接口 * <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
語句。實際的代碼可能要比這個多不少。接下來使用策略模式來進行代碼優化,也算是一次很小的重構。
與上面面向流程式的開發這裏會使用設計模式,優惠代碼結構,加強總體的擴展性。
itstack-demo-design-20-02 └── src └── main └── java └── org.itstack.demo.design ├── event │ └── MJCouponDiscount.java │ └── NYGCouponDiscount.java │ └── ZJCouponDiscount.java │ └── ZKCouponDiscount.java ├── Context.java └── ICouponDiscount.java
策略模式模型結構
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); } }
@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); }
測試結果
15:43:22.035 [main] INFO org.itstack.demo.design.test.ApiTest - 測試結果:直減優惠後金額 90 Process finished with exit code 0
@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); }
測試結果
15:43:42.695 [main] INFO org.itstack.demo.design.test.ApiTest - 測試結果:滿減優惠後金額 90 Process finished with exit code 0
@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); }
測試結果
15:44:05.602 [main] INFO org.itstack.demo.design.test.ApiTest - 測試結果:折扣9折後金額 90.00 Process finished with exit code 0
@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);
測試結果
15:44:24.700 [main] INFO org.itstack.demo.design.test.ApiTest - 測試結果:n元購優惠後金額 90 Process finished with exit code 0
100元
上折扣10元
,最終支付90元
。策略模式
、適配器模式
、組合模式
等,在一些結構上是比較類似的,可是每個模式是有本身的邏輯特色,在使用的過程當中最佳的方式是通過較多的實踐來吸收經驗,爲後續的研發設計提供更好的技術輸出。1. 重學 Java 設計模式:實戰工廠方法模式「多種類型商品不一樣接口,統一發獎服務搭建場景」
2. 重學 Java 設計模式:實戰原型模式「上機考試多套試,每人題目和答案亂序排列場景」
3. 重學 Java 設計模式:實戰橋接模式「多支付渠道(微信、支付寶)與多支付模式(刷臉、指紋)場景」
4. 重學 Java 設計模式:實戰組合模式「營銷差別化人羣發券,決策樹引擎搭建場景」
5. 重學 Java 設計模式:實戰外觀模式「基於SpringBoot開發門面模式中間件,統一控制接口白名單場景」
6. 重學 Java 設計模式:實戰享元模式「基於Redis秒殺,提供活動與庫存信息查詢場景」
7. 重學 Java 設計模式:實戰備忘錄模式「模擬互聯網系統上線過程當中,配置文件回滾場景」