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


    记录学习过程中的问题,实操总结,方便回顾。

    模板方法#

    属于行为设计模式;
    在父类中定义一个算法的框架,允许子类在不修改结果的情况下重写算法的特定步骤。
    应用场景:当多个产品中的某一功能的处理重复,那么我们可以将重复的流程单独做成类方法(父类),然后针对每个产品继承父类并实现对应方法来适配不同的产品内部执行需求(子类)。

    上述爬取不同网站的的数据,但是爬取和提取数据的流程一样,那么我们将重复的流程封装为父类方法,并实现。
    好处:如果后续新加入不同产品的相同功能,那么可以直接拿来使用。
    测试代码:

    /**
    注意使用京东类的时候进行了向上转型
    */
    @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 {
    
        private ICouponDiscount couponDiscount;
    
        public Context(ICouponDiscount couponDiscount) {
            this.couponDiscount = couponDiscount;
        }
        public BigDecimal discountAmount(T couponInfo,BigDecimal skuPrice){
            return couponDiscount.discountAmount(couponInfo,skuPrice);
        }
    }
    

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

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

    /**
         * 测试策略模式
         */
    @Test
    public void Strategy_mj(){
        Context> mjActivity = new Context<>(new MJCouponDiscount());
        HashMap 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 context = new Context<>(new ZjCouponDiscount());
        BigDecimal discountAmount = context.discountAmount(9D, new BigDecimal(100));
        log.info("测试结果,直减优惠后的金额:{}",discountAmount);
    }
    @Test
    public void Strategy_zk(){
        Context context = new Context<>(new ZKCouponDiscount());
        BigDecimal discountAmount = context.discountAmount(0.8D, new BigDecimal(100));
        log.info("测试结果,折扣优惠后的金额:{}",discountAmount);
    }
    @Test
    public void Strategy_nyg(){
        Context context = new Context<>(new NYGCouponDiscount());
        BigDecimal discountAmount = context.discountAmount(80D, new BigDecimal(100));
        log.info("测试结果,N元购优惠后的金额:{}",discountAmount);
    }
    

    策略模式地址

    工厂方法模式#

    属于创建型设计模式;
    工厂模式在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型;
    好处:提供代码的扩展性,减少if-else方法
    场景:

    1. 当我们需要替换新的对象时,但是在不同的产品或功能中都引入了,造成修改困难;(简单工厂模式)
    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 extMap = new HashMap<>();
            extMap.put("consigneeUserName", "谢飞机");
            extMap.put("consigneeUserPhone", "15200292123");
            extMap.put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");
            commodityService.sendCommodity("10001","9820198721311","1023000020112221113",extMap);
        }
    

    推荐博客
    工厂方法模式地址

    参考和学习引用#

    深入设计模式(亚历山大·什韦茨)
    重学Java设计模式

  • 相关阅读:
    中微SC8F5771模拟IIC通信——指令运行速度的探索(附编译软件与烧录软件)
    美团一面:什么是CAS?有什么优缺点?我说我只用过AtomicInteger。。。。
    接口测试3-接口依赖之token提取
    git使用.md
    .Net 7里的函数.Ctor和.CCtor是干啥用的呢?你知道吗
    事务+事务并发+事务隔离级别【Interview Question】
    opencv-4.5.2-android-sdk.zip安装教程
    jQuery学习:事件委托--新添加的元素没有监听
    hive 之with as 和create view 和create temporary table用法
    Java8将List集合转换为数组【通过流(Stream)方式】
  • 原文地址:https://www.cnblogs.com/xbhog/p/16641298.html