1. 简介
模板方法模式(Template Method Pattern)是一种行为型设计模式,它在父类中定义一个算法的框架,允许子类在不改变算法结构的情况下重写算法的某些特定步骤。这种模式主要用来解决代码重复的问题,并且提供了一个算法的统一框架,使得子类可以在这个框架下去实现特定的功能。
特点
-
代码复用:模板方法模式使得子类可以复用父类的代码,提高代码复用性。
-
扩展性:通过覆盖父类的方法,子类可以很容易地扩展新的功能。
-
控制反转:将一些步骤的控制权从子类反转到父类,父类控制流程,子类实现具体步骤。
结构
模板方法模式通常包含以下角色:
-
抽象类(Abstract Class):定义了模板方法和算法的框架。模板方法一般是一个具体方法,它定义了算法的步骤,并调用基本方法来完成算法的部分步骤。
-
基本方法(Primitive Method):在抽象类中定义的抽象方法或具体方法,是算法框架的一部分。抽象方法通常由子类实现,而具体方法则可以直接实现或由子类覆盖。
-
钩子方法(Hook Method):在抽象类中定义的可供子类覆盖的方法,不做任何事情或包含默认实现。
-
具体实现子类(Concrete Class):实现抽象类中定义的抽象方法,完成算法中可变的部分。
2. 具体案例
模拟爬⾍各类电商商品,⽣成营销推⼴海报场景
定义抽象类
java
package com.xiaokai.rule;
/**
* Author:yang
* Date:2024-10-25 10:27
* 模板方法模式通常包含以下几个角色:
* <p>
* 抽象类(Abstract Class):定义了模板方法和算法的框架。
* 具体实现子类(Concrete Class):实现抽象类中定义的模板方法中的可变部分。
* 钩子方法(Hook Method):在抽象类中定义,可以被子类重写,也可以不重写。
* 模板方法(Template Method):定义算法的框架,调用基本方法和钩子方法。
*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
/**
* 基础电商推⼴服务
* 1. ⽣成最优价商品海报
* 2. 海报含带推⼴邀请码
*/
public abstract class AbstractNetMall {
protected Logger logger = LoggerFactory.getLogger(AbstractNetMall.class);
String uId; // ⽤户ID
String uPwd; // ⽤户密码
public AbstractNetMall(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. 验证登录
Map<String, String> reptile = reptile(skuUrl); // 2. 爬⾍商品
return createBase64(reptile); // 3. 组装海报
}
// 模拟登录
protected abstract Boolean login(String uId, String uPwd);
// 爬⾍提取商品信息(登录后的优惠价格)
protected abstract Map<String, String> reptile(String skuUrl);
// ⽣成商品海报信息
protected abstract String createBase64(Map<String, String> goodsInfo);
}
当当、京东、淘宝三种行为
java
public class DDProduct extends AbstractNetMall {
public DDProduct(String uId, String uPwd) {
super(uId, uPwd);
}
@Override
protected Boolean login(String uId, String uPwd) {
// 模拟当当用户登录
logger.debug("模拟当当用户登录, uId: {},uPwd: {}", uId, uPwd);
return true;
}
@Override
protected Map<String, String> reptile(String skuUrl) {
// 匹配
Map<String, String> map = new ConcurrentHashMap<String, String>();
//Pattern p9 = Pattern.compile("(?<=title\\>).*(?=</title)");
//Matcher m9 = p9.matcher(skuUrl);
//if (m9.find()) {
// map.put("name", m9.group());
//}
map.put("name", "当当产品天下第一好····");
map.put("price", "99.00");
logger.info("模拟当当商品爬⾍解析:{} | {} 元 {}", map.get("name"),
map.get("price"), skuUrl);
return map;
}
@Override
protected String createBase64(Map<String, String> goodsInfo) {
Base64.Encoder encoder = Base64.getEncoder();
logger.info("模拟⽣成当当商品base64海报");
return encoder.encode(goodsInfo.toString().getBytes()).toString();
}
}
public class JDProduct extends AbstractNetMall {
public JDProduct(String uId, String uPwd) {
super(uId, uPwd);
}
@Override
protected Boolean login(String uId, String uPwd) {
// 模拟淘宝用户登录
logger.debug("模拟京东用户登录, uId: {},uPwd: {}", uId, uPwd);
return true;
}
@Override
protected Map<String, String> reptile(String skuUrl) {
// 匹配
Map<String, String> map = new ConcurrentHashMap<String, String>();
//Pattern p9 = Pattern.compile("(?<=title\\>).*(?=</title)");
//Matcher m9 = p9.matcher(skuUrl);
//if (m9.find()) {
// map.put("name", m9.group());
//}
map.put("name", "京东产品天下第一好····");
map.put("price", "4299.00");
logger.info("模拟京东商品爬⾍解析:{} | {} 元 {}", map.get("name"),
map.get("price"), skuUrl);
return map;
}
@Override
protected String createBase64(Map<String, String> goodsInfo) {
Base64.Encoder encoder = Base64.getEncoder();
logger.info("模拟⽣成京东商品base64海报");
return encoder.encode(goodsInfo.toString().getBytes()).toString();
}
}
public class TaoBaoProduct extends AbstractNetMall {
public TaoBaoProduct(String uId, String uPwd) {
super(uId, uPwd);
}
@Override
protected Boolean login(String uId, String uPwd) {
// 模拟淘宝用户登录
logger.debug("模拟淘宝用户登录, uId: {},uPwd: {}", uId, uPwd);
return true;
}
@Override
protected Map<String, String> reptile(String skuUrl) {
// 匹配
Map<String, String> map = new ConcurrentHashMap<String, String>();
//Pattern p9 = Pattern.compile("(?<=title\\>).*(?=</title)");
//Matcher m9 = p9.matcher(skuUrl);
//if (m9.find()) {
// map.put("name", m9.group());
//}
map.put("name", "淘宝产品天下第一好····");
map.put("price", "4799.00");
logger.info("模拟淘宝商品爬⾍解析:{} | {} 元 {}", map.get("name"),
map.get("price"), skuUrl);
return map;
}
@Override
protected String createBase64(Map<String, String> goodsInfo) {
Base64.Encoder encoder = Base64.getEncoder();
logger.info("模拟⽣成淘宝商品base64海报");
return encoder.encode(goodsInfo.toString().getBytes()).toString();
}
}
测试
java
public class MallApplication {
public static void main(String[] args) {
AbstractNetMall product = new TaoBaoProduct("xiaokai", "123456");
String goodsPoster = product.generateGoodsPoster("www.taobao.com/xiaokai.caio&mfdk");
System.out.println(goodsPoster);
}
}
模拟淘宝用户登录, uId: xiaokai,uPwd: 123456
模拟淘宝商品爬⾍解析:淘宝产品天下第一好···· | 4799.00 元 www.taobao.com/xiaokai.caio&mfdk
模拟⽣成淘宝商品base64海报
海报生成成功:[B@7907ec20
不积跬步,无以至千里 --- xiaokai