Java實(shí)現(xiàn)月餅的制作、下單和售賣(mài)功能
本文導(dǎo)讀
中秋節(jié)是中國(guó)民間的傳統(tǒng)節(jié)日,中秋節(jié)源自天象崇拜由上古時(shí)代秋夕祭月演變而來(lái)。中秋節(jié)自古便有祭月、賞月、吃月餅等民俗,流傳至今,經(jīng)久不息。
說(shuō)到月餅,我們現(xiàn)在吃的都是工廠、小作坊、自己家里制作,在電商平臺(tái)售賣(mài)或者有一些營(yíng)銷(xiāo)活動(dòng)贈(zèng)送,我們來(lái)看看Java是怎么制作月餅的,我們是否可以在代碼實(shí)現(xiàn)一個(gè)月餅售賣(mài)的架構(gòu)設(shè)計(jì)和設(shè)計(jì)模式。
借此機(jī)會(huì),我們用Lambda實(shí)現(xiàn)一遍月餅制作,下單,售賣(mài)的開(kāi)發(fā)設(shè)計(jì)模式,主要有制作月餅的工廠模式、
一、使用工廠模式制作月餅
設(shè)計(jì)模式是在大量的實(shí)踐中總結(jié)和理論化之后優(yōu)選的代碼結(jié)構(gòu)、編程風(fēng)格、以及解決問(wèn)題的思維方式。使用工廠模式,我們就無(wú)需向消費(fèi)者們暴露,我們的月餅(實(shí)例化月餅對(duì)象)的制作邏輯,就能完成月餅的制作。
1、使用工廠創(chuàng)建月餅實(shí)例
我們需要一個(gè)月餅工廠(MoonCakeFactory)或者叫月餅小作坊,在工廠里我們可以創(chuàng)建一個(gè)map 將產(chǎn)品名映射到對(duì)應(yīng)的構(gòu)造函數(shù)中,提供一個(gè)像工廠模式一樣,利用map來(lái)實(shí)例化不同對(duì)象。
/** * 一個(gè)簡(jiǎn)單的月餅制作工廠 * @author XiaoMing */ public class MoonCakeFactory { /** * 我們可以創(chuàng)建一個(gè)map 將產(chǎn)品名映射到對(duì)應(yīng)的構(gòu)造函數(shù)中 */ final static Map<String, Supplier<MoonCakeInfo>> map = new HashMap<>(); static { // 五仁的,我的最?lèi)?ài) map.put("wuRen", WuRenMoonCakeInfo::new); // 豆沙 map.put("redBeanPaste", RedBeanPasteMoonCakeInfo::new); // 棗泥 map.put("jujubePaste", JujubePasteMoonCakeInfo::new); // 蛋黃的 map.put("eggYolk", EggYolkMoonCakeInfo::new); } /** * 像工廠模式一樣,利用map來(lái)實(shí)例化不同對(duì)象 * * @param moonCakeType 月餅類(lèi)型 */ public static MoonCakeInfo createMoonCake(String moonCakeType) { // 獲取月餅供應(yīng)商 Supplier<MoonCakeInfo> moonCakeInfoSupplier = map.get(moonCakeType); if (null != moonCakeInfoSupplier) { return moonCakeInfoSupplier.get(); } throw new IllegalArgumentException("No such MoonCakeInfo" + moonCakeType); } } /** * @author XiaoMing */ public class WuRenMoonCakeInfo extends MoonCakeInfo { private String wuRen; public String getWuRen() { return wuRen; } public void setWuRen(String wuRen) { this.wuRen = wuRen; } }
2、工廠模式剖析
現(xiàn)在我們就可以試著拿到對(duì)應(yīng)的,實(shí)例化的月餅對(duì)象了
WuRenMoonCakeInfo wuRen = (WuRenMoonCakeInfo) createMoonCake("wuRen");
我們看完了這個(gè)例子,現(xiàn)在思考內(nèi)部的問(wèn)題,這么做有什么好處?為什么createMoonCake是一個(gè)static的方法?
我們制作月餅有很多餡,除了餡我們還可以取對(duì)應(yīng)餡(moonCakeType)的時(shí)候,就可以獲取到一個(gè)實(shí)例化的對(duì)象,不需要我們?cè)谑褂玫牡胤絼?chuàng)建,將工廠定義為靜態(tài)方法是一個(gè)常用技巧,稱(chēng)為靜態(tài)工廠,不需要?jiǎng)?chuàng)建方法來(lái)實(shí)例化對(duì)象,將實(shí)例化對(duì)象和創(chuàng)建方法解耦。
總結(jié)一下,工廠模式是用一個(gè)專(zhuān)業(yè)類(lèi)(工廠類(lèi))來(lái)負(fù)責(zé)一種產(chǎn)品的對(duì)象創(chuàng)建。這樣做的好處是,1、把對(duì)象的創(chuàng)建和使用分開(kāi);2、將生產(chǎn)過(guò)程集中后,便于集中管理(增刪改);3、當(dāng)實(shí)體類(lèi)有變動(dòng)時(shí),使用者不需要再去修改代碼。
二、使用策略模式限制購(gòu)買(mǎi)月餅類(lèi)型
一個(gè)禮盒中有很多類(lèi)型的月餅,有些餡并不我待見(jiàn),博主曾經(jīng)吃過(guò)一個(gè)咖啡餡月餅,這里面我們把奇奇怪怪的餡扣除去。校驗(yàn)是否為有效訂單,設(shè)置該策略不允許咖啡餡月餅和榴蓮餡的下單
1、實(shí)戰(zhàn)代碼
策略模式可以理解為一種通過(guò)算法解決一類(lèi)問(wèn)題的通用方案,策略模式包括該算法的接口,一個(gè)或多個(gè)接口的實(shí)現(xiàn)邏輯,以及策略對(duì)象,下面我們用lambda表達(dá)式實(shí)現(xiàn),Validator 相當(dāng)于一個(gè)中轉(zhuǎn)站,strategy.validatorOrder(orderType);可以通過(guò)下屬lambda實(shí)現(xiàn),也可以通過(guò)實(shí)現(xiàn)類(lèi),繼承Strategy 接口實(shí)現(xiàn)
/** * 假設(shè)為下單主流程 * 我們主要關(guān)注 策略模式下訂單類(lèi)型的校驗(yàn),這幾個(gè)步驟 */ public void submitOrder(OrderInfo orderInfo) { // ... // 校驗(yàn)是否為有效訂單,設(shè)置該策略不允許咖啡餡月餅和榴蓮餡的下單 Validator v1 = new Validator(orderType -> !orderType.equals("Coffee") || !orderType.equals("Durian")); v1.validatorOrder(orderInfo.getOrderType()); // ... } /** * @author XiaoMing */ public class Validator { private Strategy strategy; public Validator(Strategy strategy) { this.strategy = strategy; } public boolean validatorOrder(String orderType) { return strategy.validatorOrder(orderType); } } /** * @author XiaoMing */ public interface Strategy { /** * 函數(shù)式接口,通過(guò)調(diào)用 Validator時(shí)實(shí)現(xiàn) */ boolean validatorOrder(String orderType); }
一般我們也可以使用實(shí)現(xiàn)類(lèi)實(shí)現(xiàn)
/** * @author xiaoming * @date 2022/8/27-10:33 */ public class RealOrderImpl implements Strategy { @Override public boolean validatorOrder(String orderType) { System.out.println("real"); return orderType.equals("real"); } } public class O2OOrderImpl implements Strategy { @Override public boolean validatorOrder(String orderType) { System.out.println("O2O"); return orderType.equals("O2O"); } }
策略模式類(lèi)圖:
2、策略模式剖析
策略模式需要做的就是當(dāng)請(qǐng)求進(jìn)來(lái)時(shí)候,同一個(gè)入口讓他根據(jù)這個(gè)人請(qǐng)求的行為去執(zhí)行其中某一個(gè)類(lèi)中的方法。
策略接口的定義,通常包含兩個(gè)方法:獲取策略類(lèi)型的方法和處理策略業(yè)務(wù)邏輯的方法。策略接口的實(shí)現(xiàn),每種支付類(lèi)都實(shí)現(xiàn)了上述接口(基于接口而非實(shí)現(xiàn)編程),這樣我們可以靈活的替換不同的支付方式(上文代碼段就是使用lambda表達(dá)式實(shí)現(xiàn)的)。
接口只負(fù)責(zé)業(yè)務(wù)策略的定義,每個(gè)策略的具體實(shí)現(xiàn)單獨(dú)放在實(shí)現(xiàn)Impl中,我們可以使用工廠類(lèi) Factory 只負(fù)責(zé)獲取具體實(shí)現(xiàn)類(lèi),而具體調(diào)用代碼則負(fù)責(zé)業(yè)務(wù)邏輯的編排。這些實(shí)現(xiàn)用到了面向接口而非實(shí)現(xiàn)編程,滿(mǎn)足了職責(zé)單一、開(kāi)閉原則,從而達(dá)到了功能上的高內(nèi)聚低耦合、提高了可維護(hù)性、擴(kuò)展性以及代碼的可讀性。
三、模板方法模式設(shè)計(jì)月餅的優(yōu)惠決策
我們購(gòu)買(mǎi)月餅在電商業(yè)務(wù)中有很多優(yōu)惠信息,例如紅包、平臺(tái)券、商家券、滿(mǎn)減、秒殺活動(dòng)等等, 如果每個(gè)優(yōu)惠寫(xiě)一個(gè)方法那么就不方便閱讀和管理,我們可以用這種方式將代碼擴(kuò)展性做的很好假設(shè)為下單主流程,我們主要關(guān)注 優(yōu)惠決策與核銷(xiāo)->優(yōu)惠信息落庫(kù),這幾個(gè)步驟。
1、使用模板方法實(shí)現(xiàn)優(yōu)惠活動(dòng)
讓我們從模板方法模式設(shè)計(jì)月餅的優(yōu)惠決策的例子著手,看看這個(gè)模式是如何工作的。
/** * 假設(shè)為下單主流程 * 我們主要關(guān)注 優(yōu)惠決策與核銷(xiāo)->優(yōu)惠信息落庫(kù),這幾個(gè)步驟 */ public void submitOrder(List<OrderInfo> orderList) { // ... // 優(yōu)惠決策與核銷(xiāo) writeOff(orderList, couponInfos -> { // 將優(yōu)惠信息落庫(kù) transaction(orderList); }); // ... } /** * 我們購(gòu)買(mǎi)月餅在,電商業(yè)務(wù)中有很多優(yōu)惠信息,例如紅包、平臺(tái)券、商家券、滿(mǎn)減、秒殺活動(dòng)等等 * 如果每個(gè)優(yōu)惠寫(xiě)一個(gè)方法那么就不方便閱讀和管理,我們可以用這種方式將代碼擴(kuò)展性做的很好 */ public void writeOff(List<OrderInfo> orderList, Consumer<List<CouponInfo>> consumer) { // 每個(gè)優(yōu)惠信息,由自己的實(shí)現(xiàn)類(lèi)實(shí)現(xiàn) List<CouponInfo> couponInfos = consume(orderList); // 此處將結(jié)果保存 consumer.accept(couponInfos); } /** * 每個(gè)優(yōu)惠信息自己實(shí)現(xiàn) ServiceImpl */ private List<CouponInfo> consume(List<OrderInfo> orderList) { List<CouponInfo> couponInfos = new ArrayList<>(); // 核銷(xiāo)后返回信息(實(shí)現(xiàn)業(yè)務(wù)邏輯) // ... return couponInfos; } /** * 將優(yōu)惠信息落庫(kù) */ private static void transaction(List<OrderInfo> orderInfos) { }
2、模板方法剖析
模板方法模式,如果你需要采用某個(gè)算法的框架,同時(shí)又希望有一定的靈是活度,能對(duì)它的某些部分進(jìn)行改進(jìn),那么采用模板方法設(shè)計(jì)模式是比較通用的方案。這樣講有些抽象。換句話(huà)說(shuō),模板方法模式在你希望使用這個(gè)算法,但是需要對(duì)其中的某些行進(jìn)行改進(jìn),才能達(dá)到希望的效果時(shí)是非常有用的。
優(yōu)點(diǎn),1、提高代碼復(fù)用性,可以將相同部分的代碼放在抽象的父類(lèi)中;2、提高了拓展性,將不同的代碼放入不同的子類(lèi)中,通過(guò)對(duì)子類(lèi)的擴(kuò)展增加新的行為;3、實(shí)現(xiàn)了反向控制,通過(guò)一個(gè)父類(lèi)調(diào)用其子類(lèi)的操作,通過(guò)對(duì)子類(lèi)的擴(kuò)展增加新的行為。
缺點(diǎn),1、引入了抽象類(lèi),每一個(gè)不同的實(shí)現(xiàn)都需要一個(gè)子類(lèi)來(lái)實(shí)現(xiàn),導(dǎo)致類(lèi)的個(gè)數(shù)增加,從而增加了系統(tǒng)實(shí)現(xiàn)的復(fù)雜度。
場(chǎng)景,1、一次性實(shí)現(xiàn)一個(gè)算法的不變的部分,并將可變的行為留給子類(lèi)來(lái)實(shí)現(xiàn);2、各子類(lèi)中公共的行為應(yīng)被提取出來(lái)并集中到一個(gè)公共父類(lèi)中以避免代碼重復(fù)。
總結(jié)
借此中秋節(jié)機(jī)會(huì),我們實(shí)現(xiàn)一個(gè)月餅售賣(mài)的設(shè)計(jì)模式。主要使用了Lambda和設(shè)計(jì)模式的思想,實(shí)現(xiàn)月餅制作的工廠模式,下單的策略模式校驗(yàn),優(yōu)惠券操作的模板方法模式的開(kāi)發(fā)。
設(shè)計(jì)模式是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類(lèi)編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 項(xiàng)目中合理的運(yùn)用設(shè)計(jì)模式可以完美的解決很多問(wèn)題,每種模式在現(xiàn)在中都有相應(yīng)的原理來(lái)與之對(duì)應(yīng),每一個(gè)模式描述了一個(gè)在我們周?chē)粩嘀貜?fù)發(fā)生的問(wèn)題,以及該問(wèn)題的核心解決方案,這也是它能被廣泛應(yīng)用的原因。
到此這篇關(guān)于Java實(shí)現(xiàn)月餅的制作、下單和售賣(mài)的文章就介紹到這了,更多相關(guān)Java月餅內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot實(shí)現(xiàn)無(wú)限級(jí)評(píng)論回復(fù)的項(xiàng)目實(shí)踐
本文主要介紹了SpringBoot實(shí)現(xiàn)無(wú)限級(jí)評(píng)論回復(fù)的項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03Java實(shí)現(xiàn)TCP/IP協(xié)議的收發(fā)數(shù)據(jù)(服務(wù)端)代碼實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)TCP/IP協(xié)議的收發(fā)數(shù)據(jù)(服務(wù)端)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Spring實(shí)戰(zhàn)之使用Expression接口進(jìn)行表達(dá)式求值操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用Expression接口進(jìn)行表達(dá)式求值操作,結(jié)合實(shí)例形式分析了Spring操作Expression接口實(shí)現(xiàn)表達(dá)式運(yùn)算的操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2019-12-12HTTP 415錯(cuò)誤-Unsupported media type詳解
這篇文章主要介紹了HTTP 415錯(cuò)誤-Unsupported media type詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08java實(shí)現(xiàn)ArrayList根據(jù)存儲(chǔ)對(duì)象排序功能示例
這篇文章主要介紹了java實(shí)現(xiàn)ArrayList根據(jù)存儲(chǔ)對(duì)象排序功能,結(jié)合實(shí)例形式分析了java針對(duì)ArrayList的相關(guān)運(yùn)算、排序操作技巧,需要的朋友可以參考下2018-01-01