• JAVA【设计模式】模板模式


    一、定义

    在这里插入图片描述

    模板模式:指定了一系列的算法骨架(方法实现骨架),将算法的一些步骤延迟到子类中,使得子类在不改变算法结构的情况下,重新定义该算法下面的特定步骤实现。它是一种行为模式

    二、示例:

    模拟场景:
    1、模拟爬⾍各类电商商品,⽣成营销推⼴海报场景,⽽整个的爬取过程分为;模拟登录、爬取信息、⽣成海报,这三个步骤。另外每个电商网站的模拟登录、爬取信息、⽣成海报都不一样。

    模板模式设计

    抽象类,定义了模拟登录、爬取信息、⽣成海报抽象方法,由各大门户不同实现

    package com.qf.design.behavior.template.design;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.util.Map;
    
    public abstract class NetMall {
        protected Logger logger = LoggerFactory.getLogger(NetMall.class);
    
        //用户id
        private String uid;
        //用户密码
        private String uPwd;
    
        public NetMall(String uid, String uPwd) {
            this.uid = uid;
            this.uPwd = uPwd;
        }
    
        /**
         * 生成商品推广海报
         */
        public String generateGoodsPoster(String skuUrl){
            //1.验证登录
            if (!login(uid,uPwd)) return null;
    
            //2.爬虫获取网页信息
            Map<String, String> reptile = reptile(skuUrl);
    
            //3.生成商品海报信息
           return createBase64(reptile);
        }
    
        //模拟登录
        public abstract Boolean login(String uid, String uPwd);
    
        //爬虫获取网页信息
        public abstract Map<String,String> reptile(String skuUrl);
    
        //生成商品海报信息
        public abstract String createBase64(Map<String, String> goodsInfo);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    爬取数据的公共方法

    package com.qf.design.behavior.template.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;
    
    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, "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;
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    当当

    package com.qf.design.behavior.template.design.group;
    
    import com.alibaba.fastjson.JSON;
    import com.qf.design.behavior.template.design.HttpClient;
    import com.qf.design.behavior.template.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;
    
    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 Map<String, String> reptile(String skuUrl) {
            String str = HttpClient.doGet(skuUrl);
            Pattern p9 = Pattern.compile("(?<=title\\>).*(?=);
            Matcher m9 = p9.matcher(str);
            Map<String, String> map = new ConcurrentHashMap<String, 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(Map<String, String> goodsInfo) {
            BASE64Encoder encoder = new BASE64Encoder();
            logger.info("模拟⽣成当当商品base64海报");
            return encoder.encode(JSON.toJSONString(goodsInfo).getBytes());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    JD网

    package com.qf.design.behavior.template.design.group;
    
    import com.alibaba.fastjson.JSON;
    import com.qf.design.behavior.template.design.HttpClient;
    import com.qf.design.behavior.template.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;
    
    public class JDNetMall extends NetMall {
    
        public JDNetMall(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 Map<String, String> reptile(String skuUrl) {
            String str = HttpClient.doGet(skuUrl);
            Pattern p9 = Pattern.compile("(?<=title\\>).*(?=);
            Matcher m9 = p9.matcher(str);
            Map<String, String> map = new ConcurrentHashMap<String, 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;
        }
    
        @Override
        public String createBase64(Map<String, String> goodsInfo) {
            BASE64Encoder encoder = new BASE64Encoder();
            logger.info("模拟⽣成京东商品base64海报");
            return encoder.encode(JSON.toJSONString(goodsInfo).getBytes());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    taobao网

    package com.qf.design.behavior.template.design.group;
    
    import com.alibaba.fastjson.JSON;
    import com.qf.design.behavior.template.design.HttpClient;
    import com.qf.design.behavior.template.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;
    
    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 Map<String, String> reptile(String skuUrl) {
            String str = HttpClient.doGet(skuUrl);
            Pattern p9 = Pattern.compile("(?<=title\\>).*(?=);
            Matcher m9 = p9.matcher(str);
            Map<String, String> map = new ConcurrentHashMap<String, 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(Map<String, String> goodsInfo) {
            BASE64Encoder encoder = new BASE64Encoder();
            logger.info("模拟⽣成淘宝商品base64海报");
            return encoder.encode(JSON.toJSONString(goodsInfo).getBytes());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    测试:ApiTest

    package com.qf.design.behavior.template.design;
    
    
    import com.qf.design.behavior.template.design.group.DangDangNetMall;
    import com.qf.design.behavior.template.design.group.JDNetMall;
    import com.qf.design.behavior.template.design.group.TaoBaoNetMall;
    import org.junit.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class ApiTest {
        private Logger logger= LoggerFactory.getLogger(ApiTest.class);
    
        @Test
        public void jd_Test(){
            NetMall jdNetMall = new JDNetMall("1002001", "1111");
            String result = jdNetMall.generateGoodsPoster("https://item.jd.com/100008348542.html");
            logger.info("测试结果:{}",result);
        }
    
        @Test
        public void taobao_Test(){
            NetMall jdNetMall = new TaoBaoNetMall("1002001", "1111");
            String result = jdNetMall.generateGoodsPoster("https://uland.taobao.com/sem/tbsearch?refpid=mm_26632258_3504122_32538762&keyword=%E6%B7%98%E5%AE%9D&clk1=d50f2fafb28e9f66dc22575a6d3eda87&upsId=d50f2fafb28e9f66dc22575a6d3eda87");
            logger.info("测试结果:{}",result);
        }
    
    
        @Test
        public void dd_Test(){
            NetMall jdNetMall = new DangDangNetMall("1002001", "1111");
            String result = jdNetMall.generateGoodsPoster("https://product.dangdang.com/25071550.html");
            logger.info("测试结果:{}",result);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    UML关系图

    在这里插入图片描述
    总结:
    通过上⾯的实现可以看到 模版模式 在定义统⼀结构也就是执⾏标准上⾮常⽅便,也就很好的控制了后续的实现者不⽤关⼼调⽤逻辑,按照统⼀⽅式执⾏。那么类的继承者只需要关⼼具体的业务逻辑实现即可。

    另外模版模式也是为了解决⼦类通⽤⽅法,放到⽗类中设计的优化。让每⼀个⼦类只做⼦类需要完成的内容,⽽不需要关⼼其他逻辑。这样提取公⽤代码,⾏为由⽗类管理,扩展可变部分,也就⾮常有利于开发拓展和迭代。

  • 相关阅读:
    10KM无人机高清图传通信模组,低延迟、抗干扰,飞睿智能无线MESH组网模块
    正则表达式
    MySQL常用命令及其案例
    【无人机通信优化】基于粒子群算法的多跳无线网络部署优化附matlab代码
    俩个不同对象的List获取交集通过属性来判断,JDK8Stream的使用
    Android并发编程与多线程
    java计算机毕业设计济南旅游网站MyBatis+系统+LW文档+源码+调试部署
    树莓派4设置
    [NOIP1999 普及组] 导弹拦截
    代码随想录day41|343. 整数拆分96. 不同的二叉搜索树
  • 原文地址:https://blog.csdn.net/cativen/article/details/126275164