设计模式---模版模式

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

相关推荐
大白爱琴1 分钟前
使用python进行图像处理—像素级操作与图像算术(4)
开发语言·图像处理·python
华科云商xiao徐3 分钟前
Java使用Jsoup库实现通用爬虫
java·爬虫
闲敲棋子落灯华23 分钟前
java学习笔记(三)--java包的引入、访问控制、类的继承、super关键字、重载、重写、运算符、拆箱
java·后端
程序员岳焱25 分钟前
Java 使用 Spring AI 的 10 个实用技巧
java·后端·程序员
Bug改不动了29 分钟前
迁移达梦数据库过程中,如何快速识别需要改写的Mapper SQL方法
java·mybatis
小小神仙36 分钟前
JSCommon系列 - 为什么前端没有 Apache Commons?
前端·javascript·设计模式
crud37 分钟前
Spring Boot 使用 @Async 实现异步操作:从入门到实战,一文讲透
java·spring boot
代码小将1 小时前
java中static学习笔记
java·笔记·学习
std78791 小时前
VITA STANDARDS LIST,VITA 最新标准清单大全下载_ansi vita 2025
java·前端·javascript
虾球xz1 小时前
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
开发语言·c++·物联网·学习