快乐彩网站做,温州网站建设选择乐云seo,镇江企业网站建设,做网站如何购买服务器吗重学 Java 设计模式#xff1a;实战模版模式「模拟爬虫各类电商商品#xff0c;生成营销推广海报场景」
一、前言
黎明前的坚守#xff0c;的住吗#xff1f;
有人举过这样一个例子#xff0c;先给你张北大的录取通知书#xff0c;但要求你每天5点起床#xff0c;12点…重学 Java 设计模式实战模版模式「模拟爬虫各类电商商品生成营销推广海报场景」
一、前言
黎明前的坚守的住吗
有人举过这样一个例子先给你张北大的录取通知书但要求你每天5点起床12点睡觉刻苦学习勤奋上进。只要你坚持三年这张通知书就有效。如果是你你能坚持吗其实对于这个例子很难在我们的人生中出现因为它目标明确有准确的行军路线。就像你是土豪家庭家里给你安排的明明白白一样只要你按照这个方式走就不会有问题。可大多数时候我们并没有这样的路线甚至不知道多久到达自己的黎明。但谁又不渴望见到黎明呢坚持吧
不要轻易被洗脑
键盘侠⌨、网络喷壶几乎当你努力坚持一件事的时候在这条路上会遇到形形色色的人和事。有时候接收建议完善自己是有必要的但不能放弃自己的初心和底线有时候只坚持自己也是难能可贵的。子路之勇子贡之辩冉有之智此三子者皆天下之所谓难能而可贵者也。阳光和努力是这个世界最温暖的东西加油坚持好自己的选的路。
有时还好坚持了
当你为自己的一个决定而感到万分开心时是不是也非常感谢自己还好坚持了。坚持、努力、终身学习似乎在程序员这个行业是离不开的当你意愿于把这当做一份可以努力的爱好时你就会愿意为此而努力。而我们很难说只在机会要来时准备而是一直努力等待机会。也就是很多人说的别人抓住机会是因为一直在准备着。
二、开发环境
JDK 1.8Idea Maven涉及工程三个可以通过关注公众号bugstack虫洞栈回复源码下载获取(打开获取的链接找到序号18)
工程描述itstack-demo-design-21-00场景模拟工程模拟爬虫商品生成海报场景
三、模版模式介绍 图片来自https://refactoringguru.cn/design-patterns/template-method
模板模式的核心设计思路是通过在抽象类中定义抽象方法的执行顺序并将抽象方法设定为只有子类实现但不设计独立访问的方法。简单说也就是把你安排的明明白白的。 就像西游记的99八十一难基本每一关都是师傅被掳走、打妖怪、妖怪被收走具体什么妖怪你自己定义怎么打你想办法最后收走还是弄死看你本事我只定义执行顺序和基本策略具体的每一难由观音来安排。
四、案例场景模拟 在本案例中我们模拟爬虫各类电商商品生成营销推广海报场景
关于模版模式的核心点在于由抽象类定义抽象方法执行策略也就是说父类规定了好一系列的执行标准这些标准的串联成一整套业务流程。
在这个场景中我们模拟爬虫爬取各类商家的商品信息生成推广海报(海报中含带个人的邀请码)赚取商品返利。声明这里是模拟爬取并没有真的爬取
而整个的爬取过程分为模拟登录、爬取信息、生成海报这三个步骤另外
因为有些商品只有登录后才可以爬取并且登录可以看到一些特定的价格这与未登录用户看到的价格不同。不同的电商网站爬取方式不同解析方式也不同因此可以作为每一个实现类中的特定实现。生成海报的步骤基本一样但会有特定的商品来源标识。所以这样三个步骤可以使用模版模式来设定并有具体的场景做子类实现。
五、模版模式搭建工程
模版模式的业务场景可能在平时的开发中并不是很多主要因为这个设计模式会在抽象类中定义逻辑行为的执行顺序。一般情况下我们用的抽象类定义的逻辑行为都比较轻量级或者没有只是提供一些基本方法公共调用和实现。
但如果遇到适合的场景使用这样的设计模式也是非常方便的因为他可以控制整套逻辑的执行顺序和统一的输入、输出而对于实现方只需要关心好自己的业务逻辑即可。
而在我们这个场景中只需要记住这三步的实现即可模拟登录、爬取信息、生成海报
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模版模式模型结构 以上的代码结构还是比较简单的一个定义了抽象方法执行顺序的核心抽象类以及三个模拟具体的实现(京东、淘宝、当当)的电商服务。
2. 代码实现
2.1 定义执行顺序的抽象类
/*** 基础电商推广服务* 1. 生成最优价商品海报* 2. 海报含带推广邀请码*/
public abstract class NetMall {protected Logger logger LoggerFactory.getLogger(NetMall.class);String uId; // 用户IDString 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)、模拟爬取(reptile)、生成海报(createBase64)
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());}}模拟登录爬取信息这里只是把title的信息爬取后的结果截取出来。模拟创建base64图片的方法
2.3 模拟爬虫淘宝
public class TaoBaoNetMall extends NetMall {public TaoBaoNetMall(String uId, String uPwd) {super(uId, uPwd);}Overridepublic Boolean login(String uId, String uPwd) {logger.info(模拟淘宝用户登录 uId{} uPwd{}, uId, uPwd);return true;}Overridepublic 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;}Overridepublic String createBase64(MapString, String goodsInfo) {BASE64Encoder encoder new BASE64Encoder();logger.info(模拟生成淘宝商品base64海报);return encoder.encode(JSON.toJSONString(goodsInfo).getBytes());}}同上模拟登录和爬取以及创建图片的base64
2.4 模拟爬虫当当
public class DangDangNetMall extends NetMall {public DangDangNetMall(String uId, String uPwd) {super(uId, uPwd);}Overridepublic Boolean login(String uId, String uPwd) {logger.info(模拟当当用户登录 uId{} uPwd{}, uId, uPwd);return true;}Overridepublic 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;}Overridepublic String createBase64(MapString, String goodsInfo) {BASE64Encoder encoder new BASE64Encoder();logger.info(模拟生成当当商品base64海报);return encoder.encode(JSON.toJSONString(goodsInfo).getBytes());}}同上模拟登录和爬取以及创建图片的base64
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
5Y2h5YM5b6F44CQ6KGM5oOFIOaKpeS7tyDku7fmoLwg6KE5rWL44CRLeS6rOS4nCJ9Process finished with exit code 0六、总结
通过上面的实现可以看到模版模式在定义统一结构也就是执行标准上非常方便也就很好的控制了后续的实现者不用关心调用逻辑按照统一方式执行。那么类的继承者只需要关心具体的业务逻辑实现即可。另外模版模式也是为了解决子类通用方法放到父类中设计的优化。让每一个子类只做子类需要完成的内容而不需要关心其他逻辑。这样提取公用代码行为由父类管理扩展可变部分也就非常有利于开发拓展和迭代。但每一种设计模式都有自己的特定场景如果超过场景外的建设就需要额外考虑其他模式的运用。而不是非要生搬硬套否则自己不清楚为什么这么做也很难让后续者继续维护代码。而想要活学活用就需要多加练习有实践的经历。