0202年了!你还不知道模版方法设计模式?

简介: 0202年了!你还不知道模版方法设计模式?

01、什么是 Template ?

模版方法设计模式是一种行为型设计模式。官方定义理解比较隐晦,翻译成中文意思是这样的

模板方法模式在一个方法中定义一个 算法骨架,并将某些步骤推迟到 子类中实现。模板方法模式可以让子类在 不改变算法整体结构的情况下,重新定义算法中的某些步骤。

这里通过一个模版方法的UML类图来方便理解

通俗来讲 : 定义一个抽象类 AbstractTemplate,并定义一个或若干抽象方法 abstractMethod

由子类去继承抽象类的同时实现抽象方法, 在抽象类的 operation 方法中调用抽象方法,最终调用的就是不同子类实现的方法逻辑

这也就达到了官方所说的在不改变方法逻辑的情况下,重新定义了算法中的某些步骤

operation 对应官方解释里的 算法骨架abstractMethod 对应 某些步骤

读到这里不明白的朋友可以 细心看下UML类图,下面的实际应用也是根据此图进行的

02、为什么要用 Template

模版方法主要作用:复用性扩展性

复用性想必大家 日常都有使用,可能不清楚这是模版方法的特性之一

2.1 复用性

核心思想就是 父级定义公共实现由子级进行调取使用

举个例子大家就明白了,定义抽象发送消息,邮箱消息发送调取父类的 sendMessage 方法进行发送消息

这里使用 final 关键字就是不希望子类重写方法,实际应用根据场景来定义,有或没有都可以

public abstract class AbstractSendMessage {
    public final void sendMessage(Message message) {
        sendService.sendMessage(message);
    }
}

class EmailMessage extends AbstractSendMessage {
    public void sendEmailMessage(EmailMessage emailMessage) {
        Message message = buildMessage(emailMessage);
        super.sendMessage(message);
    }
}

是不是挺容易理解的,这只是复用特性的其中一种,还有几种方式都是大同小异

今天重点不在复用性,而是另外一个特性

2.2 扩展性

扩展性指的就是文初所说的,在不修改方法逻辑的前提下,变更其中的某些步骤。这里通过一个项目中实际场景来说明

03、实际运用

老规矩,先来说一下项目中是根据什么场景进行实际运用的

由于最近要重构一部分业务,原因是因为 处理数据量过大,SO

目前的思路是进行 多线程并发执行,具体业务以及解决思路不详细说明了

由于线程在项目中属于重要且珍贵的资源,阿里巴巴开发规范中明确规定 线程资源必须交由线程池进行管理。这次实际场景也是围绕 模版设计模式的扩展性来构造线程池

构造线程池

首先定义构建线程池的抽象类,其中 initParam 交由需要创建线程池的客户端实现具体细节

@Slf4j
public abstract class AbstractTreadPoolTemplate {

    // 构建初始化参数
    public abstract ThreadPoolInitParam initParam();

    // 构造线程池
    public ExecutorService buildPool() {
        ThreadPoolInitParam threadPoolInitParam = initParam();
        ExecutorService executorService =
                new ThreadPoolExecutor(threadPoolInitParam.corePoolNum,
                        threadPoolInitParam.maxPoolNum,
                        threadPoolInitParam.keepAliveTime,
                        threadPoolInitParam.timeUnit,
                        threadPoolInitParam.workQueue,
                        threadPoolInitParam.threadFactory,
                        threadPoolInitParam.rejectedExecutionHandler);
        return executorService;
    }
}

核心参数构建

由于阿里开发手册规范认为 JDK 推出 Executors 创建线程池的方法各有弊端

所以我们使用 JDK 原生的 ThreadPoolExecutor 来进行管理线程资源,但是核心参数需要根据 业务规模以及场景来定义

个人认为业务不到一定规模,正确使用 Executors 的话,并没有什么问题。这句话偷偷说,防止被怼 [笑哭]

ThreadPoolInitParam 提供有默认的参数,但是强烈推荐 根据业务量重载参数赋值方法

@Data : Lombok 提供注解,涵盖了好几个注解,自行百度吧

@Accessors(chain = true) 级联操作,set属性的方法返回对象本身

本来想使用 @RequiredArgsConstructor,考虑到还得打备注,算了吧

Lombok 不熟悉的朋友可以去点击公众号最新推送,里面有一篇介绍性文章涵盖了80%+的注解

@Data
@Accessors(chain = true)
public class ThreadPoolInitParam {
    private Integer doubleCpu = Runtime.getRuntime().availableProcessors() << 1;
    private Integer corePoolNum = doubleCpu + 1;
    private Integer maxPoolNum = doubleCpu << 1;
    private Long keepAliveTime = 0L;
    private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
    private BlockingQueue workQueue = new ArrayBlockingQueue(500);
    private RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();
    private ThreadFactory threadFactory;
    private String threadName;

    public ThreadPoolInitParam(String threadName, boolean isDaemon) {
        this.threadFactory = new InitThreadFactory(threadName, isDaemon);
        this.threadName = threadName;
    }
}

客户端实现

客户端这里通过 new 抽象类来进行重写 initParam 方法,并填入 ThreadPoolInitParam 需要的参数后创建自定义线程池

细心的读者可以看到创建线程池尾部使用的 buildPool() 方法,是不是有一丝构建的意思呢

没错,这里使用到了 构建者设计模式,只不过没有在文中进行体现,会由后续文章来进行讲解

@Bean("dataIsuExecutor")
public ExecutorService dataIsuExecutor() {
    return new AbstractTreadPoolTemplate() {
        @Override
        public ThreadPoolInitParam initParam() {
            return new ThreadPoolInitParam("dataIsuExecutor", false)
                    .setCorePoolNum(80)
                    .setMaxPoolNum(100)
                    .setKeepAliveTime(60000L)
                    .setWorkQueue(new ArrayBlockingQueue(800));
        }
    }.buildPool();
}

04、总结

到这里,带有实际场景的 模版方法设计模式 就讲完了,模版方法模式还是比较简单容易理解的

不过,看的设计模式多了之后,发现很多模式之间 大同小异。这个时候我们就需要知道不同设计模式对应的业务场景是什么,在合适的场景使用合理的模式,才能设计出 "好代码"

相关文章
|
19天前
|
设计模式 SQL 算法
设计模式了解哪些,模版模式
设计模式了解哪些,模版模式
21 0
|
3月前
|
设计模式 算法 前端开发
【设计模式】之模版方法模式
模板模式是一种非常有用的设计模式,在前端开发中经常用于定义和扩展算法流程。它通过定义一个算法骨架,并将一些具体步骤的实现延迟到子类中,实现了优雅地管理和执行操作。通过使用模板模式,我们可以提高代码的可维护性和可扩展性。然而,在应用模板模式时需要权衡其带来的优缺点,并根据具体情况进行选择。
35 1
|
9月前
|
设计模式 程序员
设计模式 | 模版方法
设计模式 | 模版方法
57 0
|
8月前
|
设计模式
设计模式之模版模式
设计模式之模版模式
37 0
|
9月前
|
设计模式 算法 前端开发
前端实现设计模式之模版方法模式
模版方法模式是一种行为型设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。通过在父类中定义算法的结构,而将具体的实现留给子类来完成,模版方法模式提供了一种统一的算法框架,同时允许子类根据需要进行自定义实现。在前端开发中,模版方法模式常用于处理具有相似流程的操作,同时保持代码的可复用性和可扩展性。本文将介绍模版方法模式的概念和应用,并提供具体的代码示例和解读。
|
9月前
|
设计模式 算法 Java
Go 语言实现模版方法设计模式
在Go语言中,可以使用接口和组合来实现模板方法模式。模板方法模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。下面是一个示例代码,演示了如何在Go中实现模板方法模式
129 0
|
设计模式 算法 程序员
设计模式轻松学【十三】模版方法模式
我们去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现。
115 0
设计模式轻松学【十三】模版方法模式
|
设计模式 算法 机器人
一句话总结殊途同归的设计模式:工厂模式=?策略模式=?模版方法模式
虽然不同的设计模式解决的问题各不相同,但从一个更高的抽象层次来看,它们通过相同的手段来实现相同的目的。本文将以更抽象的视角剖析工厂模式、策略模式、模版方法模式,以及这些模式所遵循的设计原则。
295 0
|
设计模式 算法 Java
从零开始学设计模式(十五):模版方法模式(Template Method Pattern)
模版方法模式(Template Method)定义一个操作中算法的框架,并且将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。
151 0
从零开始学设计模式(十五):模版方法模式(Template Method Pattern)
|
设计模式 Java
Java中抽象类的应用——模版方法的设计模式
Java中抽象类的应用——模版方法的设计模式
77 0