• 模板、策略以及工厂模式


    模板方法

    属于行为设计模式;

    在父类中定义一个算法的框架,允许子类在不修改结果的情况下重写算法的特定步骤。

    应用场景:当多个产品中的某一功能的处理重复,那么我们可以将重复的流程单独做成类方法(父类),然后针对每个产品继承父类并实现对应方法来适配不同的产品内部执行需求(子类)。

    上述爬取不同网站的的数据,但是爬取和提取数据的流程一样,那么我们将重复的流程封装为父类方法,并实现。

    好处:如果后续新加入不同产品的相同功能,那么可以直接拿来使用。

    测试代码:

    1. /**
    2. 注意使用京东类的时候进行了向上转型
    3. */
    4. @Test
    5. public void demo(){
    6. NetMall netMall = new JDNetMall("1000001","*******");
    7. String base64 = netMall.generateGoodsPoster("https://item.jd.com/100008348542.html");
    8. log.info("测试结果:{}", base64);
    9. }

    策略模式

    属于行为设计模式;

    其能让你定义一系列算法并将每种算法分别放入独立的类中,以使算法的对象能够互换;

    好处:能够替代大量if-else的利器;

    场景:一般是具有同类可替代的行为逻辑算法场景;不同类型的交易方式(信用卡、支付宝、微信)、生成唯一ID策略(UUID、DB自增、DB+Redis、雪花算法、Leaf算法),导航软件(公路路线,步行路线,高速路线)等,都可以使用策略模式进行行为包装,供给外部使用;

    其使用的核心点创建一个上下文策略类(策略控制器),并且必须包含一个成员变量来存储对于每种策略的引入:

    1. /**
    2. * @author xbhog
    3. * @describe:策略控制器
    4. * @date 2022/8/21
    5. */
    6. public class Context <T>{
    7. private ICouponDiscount<T> couponDiscount;
    8. public Context(ICouponDiscount<T> couponDiscount) {
    9. this.couponDiscount = couponDiscount;
    10. }
    11. public BigDecimal discountAmount(T couponInfo,BigDecimal skuPrice){
    12. return couponDiscount.discountAmount(couponInfo,skuPrice);
    13. }
    14. }

    通过构造方法来结构传递来的具体的策略,并调用计算接口。(真的很巧妙!!)上下文策略不负责选择具体的算法,相当于中间站,提供一个小屋来进行交互。

    上下文策略使用的好处:上下文可独立于具体策略。这样你就可在不修改上下文代码或其他策略的情况下添加新算法或修改已有算法了。

    看下测试(细品):

    1. /**
    2. * 测试策略模式
    3. */
    4. @Test
    5. public void Strategy_mj(){
    6. Context<Map<String, String>> mjActivity = new Context<>(new MJCouponDiscount());
    7. HashMap<String, String> map = new HashMap<>();
    8. map.put("x","100");
    9. map.put("y","10");
    10. BigDecimal discountAmount = mjActivity.discountAmount(map, new BigDecimal(100));
    11. log.info("测试结果,满减优惠后的金额:{}",discountAmount);
    12. }
    13. @Test
    14. public void Strategy_zj(){
    15. Context<Double> context = new Context<>(new ZjCouponDiscount());
    16. BigDecimal discountAmount = context.discountAmount(9D, new BigDecimal(100));
    17. log.info("测试结果,直减优惠后的金额:{}",discountAmount);
    18. }
    19. @Test
    20. public void Strategy_zk(){
    21. Context<Double> context = new Context<>(new ZKCouponDiscount());
    22. BigDecimal discountAmount = context.discountAmount(0.8D, new BigDecimal(100));
    23. log.info("测试结果,折扣优惠后的金额:{}",discountAmount);
    24. }
    25. @Test
    26. public void Strategy_nyg(){
    27. Context<Double> context = new Context<>(new NYGCouponDiscount());
    28. BigDecimal discountAmount = context.discountAmount(80D, new BigDecimal(100));
    29. log.info("测试结果,N元购优惠后的金额:{}",discountAmount);
    30. }

    工厂方法模式

    属于创建型设计模式;

    工厂模式在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型;

    好处:提供代码的扩展性,减少if-else方法

    场景:

    1. 当我们需要替换新的对象时,但是在不同的产品或功能中都引入了,造成修改困难;(简单工厂模式,但功能过多时,会造成过多的if-else)
    2. 当我们需要增加新的对象,比如奖品(兑换卡,实物商品,优惠卷)或者日志框架等类型的场景(工厂方法模式)

    工厂方法模式的核心:调整对象创建时的位置,但是需要注意的是,仅当这些产品(兑换卡,实物商品,优惠卷)具有相同的父类或者接口时,子类才能返回不同类型的产品,同时父类中的工厂方法还应将其返回类型声明为这一共有接口(每个产品具有共同的方法);

    参考图如下:

    细品测试:

    1. /**
    2. * 工厂模式
    3. * @throws Exception
    4. */
    5. @Test
    6. public void test_commodity() throws Exception{
    7. StoreFactory storeFactory = new StoreFactory();
    8. ICommodity commodityService = storeFactory.getCommodityService(3);
    9. commodityService.sendCommodity("10001","AQY1xjkUodl8LO975GdfrYUio",null,null);
    10. }
    11. @Test
    12. public void Test_coupon() throws Exception {
    13. StoreFactory storeFactory = new StoreFactory();
    14. ICommodity commodityService = storeFactory.getCommodityService(1);
    15. commodityService.sendCommodity("10001", "EGM1023938910232121323432", "791098764902132", null);
    16. }
    17. @Test
    18. public void Test_Goods() throws Exception {
    19. StoreFactory storeFactory = new StoreFactory();
    20. ICommodity commodityService = storeFactory.getCommodityService(2);
    21. HashMap<String, String> extMap = new HashMap<>();
    22. extMap.put("consigneeUserName", "谢飞机");
    23. extMap.put("consigneeUserPhone", "15200292123");
    24. extMap.put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");
    25. commodityService.sendCommodity("10001","9820198721311","1023000020112221113",extMap);
    26. }
  • 相关阅读:
    LeetCode 203.移除链表元素
    【记录】如何备份Google浏览器的历史记录?
    4. 【containerd】pull image 如何配置密码
    nuxt 不解析HTML结构bug
    http协议详解01——http协议概念及工作流程
    HackTheBox Shoppy 枚举获得账户密码 docker越权提权
    爬虫----js逆向某宝h5的sign参数
    定位消耗系统资源多的查询
    学生HTML个人网页作业作品 基于HTML+CSS+JavaScript明星个人主页(15页)
    C函数速查手册
  • 原文地址:https://blog.csdn.net/LBWNB_Java/article/details/126846317