
文档教程后端【免费下载链接】CodeGuide:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总旨在为大家提供一个清晰详细的学习教程侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助请给予支持(关注、点赞、分享)项目地址https://gitcode.com/gh_mirrors/code/CodeGuide点击查看免费下载导读本篇技术指南以 CodeGuide 仓库中《重学 Java 设计模式》系列的模板模式实战案例为主体通过模拟爬虫京东、淘宝、当当三类电商商品生成含个人邀请码的营销推广海报这一完整场景讲解模板方法模式Template Method Pattern的核心设计思想在抽象类中定义抽象方法的执行顺序将可变的具体步骤留给子类实现。读者学完后将掌握模板模式的适用场景判断、抽象模板类与具体子类的搭建方法、如何在统一业务流程中隔离变化点并能将该模式迁移到抽奖流程编排、规则串联等真实业务中。一、前言黎明前的坚守的住吗有人举过这样一个例子先给你张北大的录取通知书但要求你每天5点起床12点睡觉刻苦学习勤奋上进。只要你坚持三年这张通知书就有效。如果是你你能坚持吗其实对于这个例子很难在我们的人生中出现因为它目标明确有准确的行军路线。就像你是土豪家庭家里给你安排的明明白白一样只要你按照这个方式走就不会有问题。可大多数时候我们并没有这样的路线甚至不知道多久到达自己的黎明。但谁又不渴望见到黎明呢坚持吧不要轻易被洗脑键盘侠、网络喷壶几乎当你努力坚持一件事的时候在这条路上会遇到形形色色的人和事。有时候接收建议完善自己是有必要的但不能放弃自己的初心和底线有时候只坚持自己也是难能可贵的。阳光和努力是这个世界最温暖的东西加油坚持好自己选的路。有时还好坚持了当你为自己的一个决定而感到万分开心时是不是也非常感谢自己还好坚持了。坚持、努力、终身学习似乎在程序员这个行业是离不开的当你意愿于把这当做一份可以努力的爱好时你就会愿意为此而努力。而我们很难说只在机会要来时准备而是一直努力等待机会。也就是很多人说的别人抓住机会是因为一直在准备着。二、开发环境项目说明JDK1.8IDEIdea Maven涉及工程itstack-demo-design-21-00场景模拟工程模拟爬虫商品生成海报场景对应参考文档docs/md/develop/design-pattern/2020-07-07-重学 Java 设计模式《实战模板模式》.md三、模板模式介绍模板模式Template Method Pattern的核心设计思路是在抽象类中定义抽象方法的执行顺序并将抽象方法设定为只有子类实现但不设计独立访问的方法。简单说也就是把你安排的明明白白的——父类规定好一整套执行标准子类只负责具体某个步骤怎么做。就像西游记的九九八十一难基本每一关都是师傅被掳走、打妖怪、妖怪被收走。具体什么妖怪你自己定义怎么打你想办法最后收走还是弄死看你本事我只定义执行顺序和基本策略具体的每一难由观音来安排。说明模板模式的经典 UML 示意图可参见 refactoringguru.cn 的 template-method 主题页面本文聚焦于 Java 代码实现层面。四、案例场景模拟在本案例中我们模拟爬虫各类电商商品生成营销推广海报场景。关于模板模式的核心点在于由抽象类定义抽象方法执行策略也就是说父类规定好了一系列的执行标准这些标准串联成一整套业务流程。在这个场景中我们模拟爬虫爬取各类商家的商品信息生成推广海报海报中含带个人的邀请码赚取商品返利。声明这里是模拟爬取并没有真的爬取。而整个的爬取过程分为模拟登录、爬取信息、生成海报这三个步骤另外因为有些商品只有登录后才可以爬取并且登录可以看到一些特定的价格这与未登录用户看到的价格不同。不同的电商网站爬取方式不同解析方式也不同因此可以作为每一个实现类中的特定实现。生成海报的步骤基本一样但会有特定的商品来源标识。所以这样三个步骤可以使用模板模式来设定并由具体的场景做子类实现。五、模板模式搭建工程模板模式的业务场景可能在平时的开发中并不是很多主要因为这个设计模式会在抽象类中定义逻辑行为的执行顺序。一般情况下我们用的抽象类定义的逻辑行为都比较轻量级或者没有只是提供一些基本方法公共调用和实现。但如果遇到适合的场景使用这样的设计模式也是非常方便的因为它可以控制整套逻辑的执行顺序和统一的输入、输出而对于实现方只需要关心好自己的业务逻辑即可。而在我们这个场景中只需要记住这三步的实现即可模拟登录、爬取信息、生成海报。1. 工程结构itstack-demo-design-21-00 └── src ├── main │ └── java │ └── org.itstack.demo.design │ ├── group │ │ ├── DangDangNetMall.java │ │ ├── JDNetMall.java │ │ └── TaoBaoNetMall.java │ ├── HttpClient.java │ └── NetMall.java └── test └── java └── org.itstack.demo.design.test └── ApiTest.java以上的代码结构还是比较简单的一个定义了抽象方法执行顺序的核心抽象类NetMall以及三个模拟具体实现京东、淘宝、当当的电商服务类。2. 代码实现2.1 定义执行顺序的抽象类/** * 基础电商推广服务 * 1. 生成最优价商品海报 * 2. 海报含带推广邀请码 */ public abstract class NetMall { protected Logger logger LoggerFactory.getLogger(NetMall.class); String uId; // 用户ID String uPwd; // 用户密码 public NetMall(String uId, String uPwd) { this.uId uId; this.uPwd uPwd; } /** * 生成商品推广海报 * * param skuUrl 商品地址(京东、淘宝、当当) * return 海报图片base64位信息 */ public String generateGoodsPoster(String skuUrl) { if (!login(uId, uPwd)) return null; // 1. 验证登录 MapString, String reptile reptile(skuUrl); // 2. 爬虫商品 return createBase64(reptile); // 3. 组装海报 } // 模拟登录 protected abstract Boolean login(String uId, String uPwd); // 爬虫提取商品信息(登录后的优惠价格) protected abstract MapString, String reptile(String skuUrl); // 生成商品海报信息 protected abstract String createBase64(MapString, String goodsInfo); }这个类是此设计模式的灵魂关键点在于定义可被外部访问的方法generateGoodsPoster用于生成商品推广海报generateGoodsPoster在方法中定义抽象方法的执行顺序1. 验证登录 → 2. 爬虫商品 → 3. 组装海报其中login失败时直接返回null终止流程这是模板方法中常见的前置校验骨架逻辑提供三个具体的抽象方法让外部继承方实现模拟登录login、模拟爬取reptile、生成海报createBase64。从源码结构可以推断login方法被设计为protected abstract即只允许子类实现、不允许外部独立访问这正是模板模式将抽象方法设定为只有子类实现但不设计独立访问的核心体现。外部唯一入口是generateGoodsPoster它保证所有调用方都必须按统一流程执行。2.2 模拟爬虫京东public class JDNetMall extends NetMall { public JDNetMall(String uId, String uPwd) { super(uId, uPwd); } public Boolean login(String uId, String uPwd) { logger.info(模拟京东用户登录 uId{} uPwd{}, uId, uPwd); return true; } public MapString, String reptile(String skuUrl) { String str HttpClient.doGet(skuUrl); Pattern p9 Pattern.compile((?title\\).*(?/title)); Matcher m9 p9.matcher(str); MapString, String map new ConcurrentHashMapString, String(); if (m9.find()) { map.put(name, m9.group()); } map.put(price, 5999.00); logger.info(模拟京东商品爬虫解析{} | {} 元 {}, map.get(name), map.get(price), skuUrl); return map; } public String createBase64(MapString, String goodsInfo) { BASE64Encoder encoder new BASE64Encoder(); logger.info(模拟生成京东商品base64海报); return encoder.encode(JSON.toJSONString(goodsInfo).getBytes()); } }实现要点模拟登录打印日志后直接返回true实际业务中这里可替换为真实的 Cookie/Session 登录逻辑爬取信息通过HttpClient.doGet(skuUrl)请求商品页再用正则(?title\\).*(?/title)把title标签中的商品名截取出来并模拟写入一个登录后的价格5999.00模拟创建 base64 图片将商品信息JSON.toJSONString序列化后用BASE64Encoder编码为 base64 字符串作为海报返回。2.3 模拟爬虫淘宝public class TaoBaoNetMall extends NetMall { public TaoBaoNetMall(String uId, String uPwd) { super(uId, uPwd); } Override public Boolean login(String uId, String uPwd) { logger.info(模拟淘宝用户登录 uId{} uPwd{}, uId, uPwd); return true; } Override public MapString, String reptile(String skuUrl) { String str HttpClient.doGet(skuUrl); Pattern p9 Pattern.compile((?title\\).*(?/title)); Matcher m9 p9.matcher(str); MapString, String map new ConcurrentHashMapString, String(); if (m9.find()) { map.put(name, m9.group()); } map.put(price, 4799.00); logger.info(模拟淘宝商品爬虫解析{} | {} 元 {}, map.get(name), map.get(price), skuUrl); return map; } Override public String createBase64(MapString, String goodsInfo) { BASE64Encoder encoder new BASE64Encoder(); logger.info(模拟生成淘宝商品base64海报); return encoder.encode(JSON.toJSONString(goodsInfo).getBytes()); } }同上模拟登录和爬取以及创建图片的 base64与京东实现类的差异点仅在日志标识与模拟价格4799.00验证了相同的流程骨架、不同的步骤实现这一模板模式的本质。2.4 模拟爬虫当当public class DangDangNetMall extends NetMall { public DangDangNetMall(String uId, String uPwd) { super(uId, uPwd); } Override public Boolean login(String uId, String uPwd) { logger.info(模拟当当用户登录 uId{} uPwd{}, uId, uPwd); return true; } Override public MapString, String reptile(String skuUrl) { String str HttpClient.doGet(skuUrl); Pattern p9 Pattern.compile((?title\\).*(?/title)); Matcher m9 p9.matcher(str); MapString, String map new ConcurrentHashMapString, String(); if (m9.find()) { map.put(name, m9.group()); } map.put(price, 4548.00); logger.info(模拟当当商品爬虫解析{} | {} 元 {}, map.get(name), map.get(price), skuUrl); return map; } Override public String createBase64(MapString, String goodsInfo) { BASE64Encoder encoder new BASE64Encoder(); logger.info(模拟生成当当商品base64海报); return encoder.encode(JSON.toJSONString(goodsInfo).getBytes()); } }同上模拟登录和爬取以及创建图片的 base64模拟价格4548.00与京东、淘宝不同再次印证公共流程在父类、差异化细节在子类的分工。3. 测试验证3.1 编写测试类/** * 测试链接 * 京东https://item.jd.com/100008348542.html * 淘宝https://detail.tmall.com/item.htm * 当当http://product.dangdang.com/1509704171.html */ Test public void test_NetMall() { NetMall netMall new JDNetMall(1000001,*******); String base64 netMall.generateGoodsPoster(https://item.jd.com/100008348542.html); logger.info(测试结果{}, base64); }测试类提供了三个商品链接也可以是其他商品的链接爬取的过程模拟爬取京东商品可以替换为其他商品服务new JDNetMall、new TaoBaoNetMall、new DangDangNetMall——替换子类实例即可复用整套模板流程这正是模板模式带来的可扩展性。3.2 测试结果23:33:13.616 [main] INFO org.itstack.demo.design.NetMall - 模拟京东用户登录 uId1000001 uPwd******* 23:33:15.038 [main] INFO org.itstack.demo.design.NetMall - 模拟京东商品爬虫解析【AppleiPhone 11】Apple iPhone 11 (A2223) 128GB 黑色 移动联通电信4G手机 双卡双待【行情 报价 价格 评测】-京东 | 5999.00 元 https://item.jd.com/100008348542.html 23:33:15.038 [main] INFO org.itstack.demo.design.NetMall - 模拟生成京东商品base64海报 23:33:15.086 [main] INFO org.itstack.demo.design.test.ApiTest - 测试结果eyJwcmljZSI6IjU5OTkuMDAiLCJuYW1lIjoi44CQQXBwbGVpUGhvbmUgMTHjgJFBcHBsZSBpUGhv bmUgMTEgKEEyMjIzKSAxMjhHQiDpu5HoibIg56e75Yqo6IGU6YCa55S15LhNEfmiYvmnLog5YM 5Y2h5YM5b6F44CQ6KGM5oOFIOaKpeS7tyDku7fmoCwg6KE5rWL44CRLeS6rOS4nCJ9 Process finished with exit code 0从运行日志可以清晰看到模板方法的执行链路登录 → 爬取解析 → 生成海报三个步骤按抽象类编排的顺序依次输出最终generateGoodsPoster返回 base64 编码的海报内容整个流程对外部调用方完全透明。六、在真实项目中的延伸应用源码佐证模板模式并不是一个演示型模式在 CodeGuide 仓库的真实业务项目中同样以抽象类编排流程 子类实现步骤的结构被广泛落地1. 抽奖流程的模板化编排在抽奖项目 docs/md/project/lottery/Part-2/第06节模板模式处理抽奖流程.md 中使用模板方法设计模式优化抽奖过程方法实现核心思路如下以抽象类AbstractDrawBase编排定义抽奖流程定义抽象方法由类DrawExecImpl做具体实现标准化的抽奖执行流程包括五步根据入参策略 ID 获取抽奖策略配置校验和处理抽奖策略的数据初始化到内存获取被排除掉的抽奖列表奖品库存为空、或风控策略不允许的用户奖品执行抽奖算法包装中奖结果。该章节明确说明如果在一个类的一个方法中顺序开发这些内容虽然也能实现但代码不易维护、不方便在各个流程节点扩展其他功能、也会使一个类的代码越来越庞大因此对于这种可以制定标准流程的功能逻辑使用模板方法模式非常合适——这与本文海报生成场景的动机完全一致。2. 模板模式串联抽奖规则在大营销平台项目 docs/md/project/big-market/api/第9节模板模式串联抽奖规则.md 中通过模板模式把责任链、规则树整合进抽奖过程定义出抽奖的标准过程让子类做具体调用功能实现整个抽奖策略过程包括责任链进行抽奖计算 → 基于抽奖计算结果对基础抽奖进行规则树的过滤 → 最终返回抽奖结果左侧的业务流程可以通过抽象类定义的调用顺序右侧的具体操作可以放到实现了抽象类的子类来做具体实现通过这样的方式在后续看代码时能直接通过抽象类的模板结构知道这块代码在做什么要看细节则进入到每个功能实现里去。这一工程实践恰好印证了模板模式在真实业务中的核心价值把流程结构与步骤实现解耦让代码的可读性、可扩展性、可维护性同时得到保障。这也是学习设计模式时值得提炼的模型结构——通用的模型结构可以解决很多同类的问题。七、总结通过上面的实现可以看到模板模式在定义统一结构、也就是执行标准上非常方便很好的控制了后续的实现者不用关心调用逻辑按照统一方式执行。那么类的继承者只需要关心具体的业务逻辑实现即可。另外模板模式也是为了解决子类通用方法放到父类中设计的优化让每一个子类只做子类需要完成的内容而不需要关心其他逻辑。这样提取公用代码、行为由父类管理、扩展可变部分非常有利于开发的拓展和迭代。但每一种设计模式都有自己的特定场景如果超过场景外的建设就需要额外考虑其他模式的运用而不是非要生搬硬套否则自己不清楚为什么这么做也很难让后续者继续维护代码。而想要活学活用就需要多加练习有实践的经历。八、延伸阅读重学 Java 设计模式《实战策略模式》与模板模式同属行为型模式解决算法族的动态切换问题可与模板模式的流程固定、步骤可变形成对照重学 Java 设计模式《实战责任链模式》在抽奖规则过滤等场景中常与模板模式搭配使用第06节模板模式处理抽奖流程模板模式在真实抽奖业务中的落地实现第9节模板模式串联抽奖规则模板模式整合责任链、规则树的标准过程定义。赞分享文档教程后端【免费下载链接】CodeGuide:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总旨在为大家提供一个清晰详细的学习教程侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助请给予支持(关注、点赞、分享)项目地址https://gitcode.com/gh_mirrors/code/CodeGuide点击查看免费下载相关推荐重学 Java 设计模式工厂方法模式实战——多种类型商品不同接口下的统一发奖服务设计重学 Java 设计模式工厂方法模式实战——多种类型商品不同接口下的统一发奖服务设计 本文以「积分兑换发奖」这一营销业务场景为主线先演示用 if/else文档教程后端CogAgent任务模板库电商平台商品筛选的视觉指令模板设计CogAgent任务模板库电商平台商品筛选的视觉指令模板设计 引言电商筛选的视觉交互痛点 你是否曾在电商平台上花费大量时间筛选商品面对琳琅满目的商品列表和CRMEB Java商城商品管理模块从发布到营销的完整流程CRMEB Java商城商品管理模块从发布到营销的完整流程 CRMEB Java商城系统是一款基于SpringBoot Vue UniApp的全栈开源后端前端电商创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考