独立访问
的方法。模板模式的业务场景可能在世的开发中并不是很多,主要因为这个设计模式会在抽象类中定义逻辑行为的执行顺序。
一般情况下,我们用的抽象类定义的逻辑行为都比较轻量级或者没有,只有提供一些基本方法公共调用和实现。
模拟登录
、爬取信息
、生成海报
。<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.62version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.5version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>jcl-over-slf4jartifactId>
<version>1.7.5version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.0.9version>
<exclusions>
<exclusion>
<artifactId>slf4j-apiartifactId>
<groupId>org.slf4jgroupId>
exclusion>
exclusions>
dependency>
dependencies>
design-step-22
|——src
|——main
|--java
|--com.lino.design
|--impl
| |--DangDangNetMall.java
| |--JDNetMall.java
| |--TaoBaoNetMall.java
|-HttpClient.java
|-NetMall.java
|--test
|--com.lino.design.test
|-ApiTest.java
京东
、淘宝
、当当
)的电商服务。HttpClient.java
package com.lino.design;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
/**
* @description: http请求类
*/
public class HttpClient {
public static String doGet(String httpUrl) {
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;
try {
// 创建远程url连接对象
URL url = new URL(httpUrl);
// 通过远程url连接对象打开一个连接,强转成HttpURLConnection
connection = (HttpURLConnection) url.openConnection();
// 设置连接方式:get
connection.setRequestMethod("GET");
// 设置连接主机服务器的超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取远程返回的数据时间:60000毫秒
connection.setReadTimeout(60000);
// 发送请求
connection.connect();
// 通过connection连接,获取输入流
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 封装输入流is,并指定字符集
br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
// 存放数据
StringBuilder sbf = new StringBuilder();
String temp = null;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭远程连接
assert connection != null;
connection.disconnect();
}
return result;
}
}
NetMall.java
package com.lino.design;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.regex.Pattern;
/**
* @description: 抽象模板
*/
public abstract class NetMall {
protected Logger logger = LoggerFactory.getLogger(NetMall.class);
protected final Pattern p9 = Pattern.compile("(?<=title\\>).*(?=);
/**
* 用户ID
*/
String uId;
/**
* 用户密码
*/
String uPwd;
public NetMall(String uId, String uPwd) {
this.uId = uId;
this.uPwd = uPwd;
}
/**
* 生成商品推广海报
*
* @param skuUrl 商品url地址
* @return 推广海报
*/
public String generateGoodsPoster(String skuUrl) {
// 1.验证登录
if (!login(uId, uPwd)) {
return null;
}
// 2.爬虫商品
Map<String, String> reptile = reptile(skuUrl);
// 3.组装海报
return createBase64(reptile);
}
/**
* 模拟登录
*
* @param uId 用户ID
* @param uPwd 用户密码
* @return 登录结果
*/
protected abstract Boolean login(String uId, String uPwd);
/**
* 爬虫提取商品信息(登录后的优惠价格)
*
* @param skuUrl 商品Url地址
* @return 商品信息
*/
protected abstract Map<String, String> reptile(String skuUrl);
/**
* 生成商品推广海报
*
* @param goodsInfo 商品信息
* @return 推广海报
*/
protected abstract String createBase64(Map<String, String> goodsInfo);
}
generateGoodsPoster
,用于生成商品推广海报。generateGoodsPoster
在方法中定义抽象方法的执行顺序 1、2、3
步。login
:模拟登录。reptile
:爬虫提取商品信息(登录后的优惠价格)。createBase64
:生成商品推广海报。DangDangNetMall.java
package com.lino.design.impl;
import com.alibaba.fastjson.JSON;
import com.lino.design.HttpClient;
import com.lino.design.NetMall;
import sun.misc.BASE64Encoder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @description: 当当抽象实现类
*/
public class DangDangNetMall extends NetMall {
public DangDangNetMall(String uId, String uPwd) {
super(uId, uPwd);
}
@Override
protected Boolean login(String uId, String uPwd) {
logger.info("模拟当当用户登录 uId:{} uPwd:{}", uId, uPwd);
return true;
}
@Override
protected Map<String, String> reptile(String skuUrl) {
String str = HttpClient.doGet(skuUrl);
Matcher m9 = p9.matcher(str);
Map<String, String> map = new ConcurrentHashMap<>();
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
protected String createBase64(Map<String, String> goodsInfo) {
BASE64Encoder encoder = new BASE64Encoder();
logger.info("模拟生成当当商品base64海报");
return encoder.encode(JSON.toJSONString(goodsInfo).getBytes());
}
}
JDNetMall.java
package com.lino.design.impl;
import com.alibaba.fastjson.JSON;
import com.lino.design.HttpClient;
import com.lino.design.NetMall;
import sun.misc.BASE64Encoder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @description: 京东抽象实现类
*/
public class JDNetMall extends NetMall {
public JDNetMall(String uId, String uPwd) {
super(uId, uPwd);
}
@Override
protected Boolean login(String uId, String uPwd) {
logger.info("模拟京东用户登录 uId:{} uPwd:{}", uId, uPwd);
return true;
}
@Override
protected Map<String, String> reptile(String skuUrl) {
String str = HttpClient.doGet(skuUrl);
Matcher m9 = p9.matcher(str);
Map<String, String> map = new ConcurrentHashMap<>();
if (m9.find()) {
map.put("name", m9.group());
}
map.put("price", "5999.00");
logger.info("模拟京东商品爬虫解析:{} | {} 元 {}", map.get("name"), map.get("price"), skuUrl);
return map;
}
@Override
protected String createBase64(Map<String, String> goodsInfo) {
BASE64Encoder encoder = new BASE64Encoder();
logger.info("模拟生成京东商品base64海报");
return encoder.encode(JSON.toJSONString(goodsInfo).getBytes());
}
}
TaoBaoNetMall.java
package com.lino.design.impl;
import com.alibaba.fastjson.JSON;
import com.lino.design.HttpClient;
import com.lino.design.NetMall;
import sun.misc.BASE64Encoder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
/**
* @description: 淘宝抽象实现类
*/
public class TaoBaoNetMall extends NetMall {
public TaoBaoNetMall(String uId, String uPwd) {
super(uId, uPwd);
}
@Override
protected Boolean login(String uId, String uPwd) {
logger.info("模拟淘宝用户登录 uId:{} uPwd:{}", uId, uPwd);
return true;
}
@Override
protected Map<String, String> reptile(String skuUrl) {
String str = HttpClient.doGet(skuUrl);
Matcher m9 = p9.matcher(str);
Map<String, String> map = new ConcurrentHashMap<>();
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
protected String createBase64(Map<String, String> goodsInfo) {
BASE64Encoder encoder = new BASE64Encoder();
logger.info("模拟生成淘宝商品base64海报");
return encoder.encode(JSON.toJSONString(goodsInfo).getBytes());
}
}
模拟登录、爬取信息、生成海报由三个实现类分别实现。
ApiTest.java
package com.lino.design.test;
import com.lino.design.NetMall;
import com.lino.design.impl.JDNetMall;
import jdk.nashorn.internal.scripts.JD;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @description: 单元测试
*/
public class ApiTest {
private Logger logger = LoggerFactory.getLogger(ApiTest.class);
private String JD_URL = "https://item.jd.com/100008348542.html";
private String TAO_BAO_URL = "https://detail.tmall.com/item.htm";
private String DANG_DANG_URL = "http://product.dangdang.com/1509704171.html";
@Test
public void test_NetMall() {
NetMall netMall = new JDNetMall("100001", "******");
String base64 = netMall.generateGoodsPoster(JD_URL);
logger.info("测试结果:{}", base64);
}
}
new JDNetMall
、 new DangDangNetMall
、 new TaoBaoNetMall
测试结果
10:36:08.491 [main] INFO com.lino.design.NetMall - 模拟京东用户登录 uId:100001 uPwd:******
10:36:09.582 [main] INFO com.lino.design.NetMall - 模拟京东商品爬虫解析:【AppleiPhone 11】Apple iPhone 11 (A2223) 128GB 黑色 移动联通电信4G手机 双卡双待【行情 报价 价格 评测】-京东 | 5999.00 元 https://item.jd.com/100008348542.html
10:36:09.582 [main] INFO com.lino.design.NetMall - 模拟生成京东商品base64海报
10:36:09.615 [main] INFO com.lino.design.test.ApiTest - 测试结果:eyJwcmljZSI6IjU5OTkuMDAiLCJuYW1lIjoi44CQQXBwbGVpUGhvbmUgMTHjgJFBcHBsZSBpUGhv
bmUgMTEgKEEyMjIzKSAxMjhHQiDpu5HoibIg56e75Yqo6IGU6YCa55S15L+hNEfmiYvmnLog5Y+M
5Y2h5Y+M5b6F44CQ6KGM5oOFIOaKpeS7tyDku7fmoLwg6K+E5rWL44CRLeS6rOS4nCJ9