模板、策略以及工廠模式

記錄學習過程中的問題,實操總結,方便回顧。

模板方法

屬於行爲設計模式;
在父類中定義一個算法的框架,允許子類在不修改結果的情況下重寫算法的特定步驟。
應用場景:當多個產品中的某一功能的處理重複,那麼我們可以將重複的流程單獨做成類方法(父類),然後針對每個產品繼承父類並實現對應方法來適配不同的產品內部執行需求(子類)。

上述爬取不同網站的的數據,但是爬取和提取數據的流程一樣,那麼我們將重複的流程封裝爲父類方法,並實現。
好處:如果後續新加入不同產品的相同功能,那麼可以直接拿來使用。
測試代碼:

/**
注意使用京東類的時候進行了向上轉型
*/
@Test
    public void demo(){
        NetMall netMall = new JDNetMall("1000001","*******");
        String base64 = netMall.generateGoodsPoster("https://item.jd.com/100008348542.html");
        log.info("測試結果:{}", base64);
    }

模板模式地址

策略模式

屬於行爲設計模式;
其能讓你定義一系列算法並將每種算法分別放入獨立的類中,以使算法的對象能夠互換;
好處:能夠替代大量if-else的利器;
場景:一般是具有同類可替代的行爲邏輯算法場景;不同類型的交易方式(信用卡、支付寶、微信)、生成唯一ID策略(UUID、DB自增、DB+Redis、雪花算法、Leaf算法),導航軟件(公路路線,步行路線,高速路線)等,都可以使用策略模式進行行爲包裝,供給外部使用;
其使用的核心點創建一個上下文策略類(策略控制器),並且必須包含一個成員變量來存儲對於每種策略的引入:

/**
 * @author xbhog
 * @describe:策略控制器
 * @date 2022/8/21
 */
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 Strategy_mj(){
    Context<Map<String, String>> mjActivity = new Context<>(new MJCouponDiscount());
    HashMap<String, String> map = new HashMap<>();
    map.put("x","100");
    map.put("y","10");
    BigDecimal discountAmount = mjActivity.discountAmount(map, new BigDecimal(100));
    log.info("測試結果,滿減優惠後的金額:{}",discountAmount);
}
@Test
public void Strategy_zj(){
    Context<Double> context = new Context<>(new ZjCouponDiscount());
    BigDecimal discountAmount = context.discountAmount(9D, new BigDecimal(100));
    log.info("測試結果,直減優惠後的金額:{}",discountAmount);
}
@Test
public void Strategy_zk(){
    Context<Double> context = new Context<>(new ZKCouponDiscount());
    BigDecimal discountAmount = context.discountAmount(0.8D, new BigDecimal(100));
    log.info("測試結果,折扣優惠後的金額:{}",discountAmount);
}
@Test
public void Strategy_nyg(){
    Context<Double> context = new Context<>(new NYGCouponDiscount());
    BigDecimal discountAmount = context.discountAmount(80D, new BigDecimal(100));
    log.info("測試結果,N元購優惠後的金額:{}",discountAmount);
}

策略模式地址

工廠方法模式

屬於創建型設計模式;
工廠模式在父類中提供一個創建對象的方法,允許子類決定實例化對象的類型;
好處:提供代碼的擴展性,減少if-else方法
場景:

  1. 當我們需要替換新的對象時,但是在不同的產品或功能中都引入了,造成修改困難;(簡單工廠模式,但功能過多時,會造成過多的if-else)
  2. 當我們需要增加新的對象,比如獎品(兌換卡,實物商品,優惠卷)或者日誌框架等類型的場景(工廠方法模式)

工廠方法模式的核心:調整對象創建時的位置,但是需要注意的是,僅當這些產品(兌換卡,實物商品,優惠卷)具有相同的父類或者接口時,子類才能返回不同類型的產品,同時父類中的工廠方法還應將其返回類型聲明爲這一共有接口(每個產品具有共同的方法);
參考圖如下:

細品測試:

/**
     * 工廠模式
     * @throws Exception
     */
    @Test
    public void  test_commodity() throws Exception{
        StoreFactory storeFactory = new StoreFactory();
        ICommodity commodityService = storeFactory.getCommodityService(3);
        commodityService.sendCommodity("10001","AQY1xjkUodl8LO975GdfrYUio",null,null);
    }
    @Test
    public void Test_coupon() throws Exception {
        StoreFactory storeFactory = new StoreFactory();
        ICommodity commodityService = storeFactory.getCommodityService(1);
        commodityService.sendCommodity("10001", "EGM1023938910232121323432", "791098764902132", null);
    }
    @Test
    public void Test_Goods() throws Exception {
        StoreFactory storeFactory = new StoreFactory();
        ICommodity commodityService = storeFactory.getCommodityService(2);
        HashMap<String, String> extMap = new HashMap<>();
        extMap.put("consigneeUserName", "謝飛機");
        extMap.put("consigneeUserPhone", "15200292123");
        extMap.put("consigneeUserAddress", "吉林省.長春市.雙陽區.XX街道.檀溪苑小區.#18-2109");
        commodityService.sendCommodity("10001","9820198721311","1023000020112221113",extMap);
    }

推薦博客
工廠方法模式地址

參考和學習引用

深入設計模式(亞歷山大·什韋茨)
重學Java設計模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章