浅析Java设计模式【3.6】——模板方法

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Java常用设计模式,模板模式

1. 目录

temple

2. 概念

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构,即可重定义该算法的某些特定步骤。

可以理解为 用抽象类存放相同逻辑,再声明一些抽象方法来胁迫子类实现剩余的逻辑。不同的子类实现不同抽象方法,即不同的剩余逻辑。

综述,它是一种自上而下的模式,类似于企业决策,决策者制定相关流程,执行层负责具体实现。

3. 应用场景

局部场景下,实现相同,但在个别细节上略有差异。

4. 优缺点

4.1. 优点

  • 实现代码复用率高
  • 局部实现带来的调整,对整体影响小

4.2. 缺点

  • 模板和子类的耦合性高,如要对模板中的算法骨架进行变更,会影响子类变化

5. 实现

这里用一个登录后的校验密码这个场景来举例。


public class UserService {

    public final boolean verifyPassWord(String userId,String password) {
        String userPassWord = getById(userId);
        return userPassWord.equalsIgnoreCase(password);
    }

    private String getById(String userId) {
        // TODO: 从数据库读取
        return null;
    }
}

因为数据库读取用户信息比较频繁而且属于IO操作,比较影响效率,我们很多时候把热点数据放到缓存,减少跟数据库的之间的IO操作。那用什么缓存实现?不同的场景有不同的选型,所以此处,我们只写出要缓存的定义,具体实现交由子类。

5.1. 抽象类


public abstract class UserService {

    /** 校验密码
     * @author <a href="https://github.com/rothschil">Sam</a>
     * @date 2022/8/5-12:58
     * @param userId
     * @param password
     * @return boolean
     **/
    public final boolean verifyPassWord(String userId,String password) {
        String userPassWord = getById(userId);
        return userPassWord.equalsIgnoreCase(password);
    }

    private String getById(String userId) {
        //  1、getByCache
        String userPassWord = getCache(userId);
        //  2、缓存没有,从数据库中获取
        if(StringUtils.isEmpty(userPassWord)){
            userPassWord =readDb(userId);
        }
        //  3、写入缓存
        if(StringUtils.isEmpty(userPassWord)){
            putCache(userId,userPassWord);
        }
        return userPassWord;
    }

    protected abstract String getCache(String userId) ;

    protected abstract String putCache(String userId,String userPassWord) ;

    private String readDb(String userId) {
        return "";
    }
}

小结:因为声明抽象方法,所以整个类也必须声明为抽象类。 重点在 getCache(String userId)putCache(String userId,String userPassWord) ,具体实现交由子类,子类具体如何实现,就由子类根据实际情况完善。

5.2. 子类实现

5.2.1. Redis实现


public class RedisService extends UserService {
    private RedisClient client = RedisClient.create("redis://localhost:6379");

    protected String getCache(String key) {
        try (StatefulRedisConnection<String, String> connection = client.connect()) {
            RedisCommands<String, String> commands = connection.sync();
            return commands.get(key);
        }
    }

    protected void putCache(String key, String value) {
        try (StatefulRedisConnection<String, String> connection = client.connect()) {
            RedisCommands<String, String> commands = connection.sync();
            commands.set(key, value);
        }
    }
}

5.2.2. SpringCache站点实现


public class SpringCacheService extends UserService {
    

    @Cacheable(key = "'key'")
    protected String getCache(String key) {

    }

    @CachePut(key = "'key'",value = "'value'",)
    protected void putCache(String key, String value) {
        
    }
}

6. 综述

模板设计模式核心思想是:父类定义骨架,子类实现某些细节。

在某些场景下为了防止子类重写父类的骨架方法,可以在父类中对骨架方法使用 final 。对于需要子类实现的抽象方法,一般声明为 protected ,使得这些方法对外部客户端不可见。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
2月前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
105 9
|
5天前
|
存储 Java 索引
Java快速入门之数组、方法
### Java快速入门之数组与方法简介 #### 一、数组 数组是一种容器,用于存储同种数据类型的多个值。定义数组时需指定数据类型,如`int[]`只能存储整数。数组的初始化分为静态和动态两种: - **静态初始化**:直接指定元素,系统自动计算长度,如`int[] arr = {1, 2, 3};` - **动态初始化**:手动指定长度,系统给定默认值,如`int[] arr = new int[3];` 数组访问通过索引完成,索引从0开始,最大索引为`数组.length - 1`。遍历数组常用`for`循环。常见操作包括求和、找最值、统计特定条件元素等。
|
1天前
|
Java
Java快速入门之类、对象、方法
本文简要介绍了Java快速入门中的类、对象和方法。首先,解释了类和对象的概念,类是对象的抽象,对象是类的具体实例。接着,阐述了类的定义和组成,包括属性和行为,并展示了如何创建和使用对象。然后,讨论了成员变量与局部变量的区别,强调了封装的重要性,通过`private`关键字隐藏数据并提供`get/set`方法访问。最后,介绍了构造方法的定义和重载,以及标准类的制作规范,帮助初学者理解如何构建完整的Java类。
|
2天前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
33 12
|
3天前
|
算法 Java API
Java 方法注释:规范、实用和高质量的写法
本文深入探讨了如何编写高质量的 Java 方法注释
25 11
|
3天前
|
SQL Java 数据库连接
【潜意识Java】Java中JDBC过时方法的替代方案以及JDBC为什么过时详细分析
本文介绍了JDBC中一些常见过时方法及其替代方案。
21 5
|
2月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
2月前
|
安全 Java 开发者
Java中WAIT和NOTIFY方法必须在同步块中调用的原因
在Java多线程编程中,`wait()`和`notify()`方法是实现线程间协作的关键。这两个方法必须在同步块或同步方法中调用,这一要求背后有着深刻的原因。本文将深入探讨为什么`wait()`和`notify()`方法必须在同步块中调用,以及这一机制如何确保线程安全和避免死锁。
61 4
|
2月前
|
Java
深入探讨Java中的中断机制:INTERRUPTED和ISINTERRUPTED方法详解
在Java多线程编程中,中断机制是协调线程行为的重要手段。了解和正确使用中断机制对于编写高效、可靠的并发程序至关重要。本文将深入探讨Java中的`Thread.interrupted()`和`Thread.isInterrupted()`方法的区别及其应用场景。
88 4

热门文章

最新文章