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


    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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    5.1. 抽象类

    
    public abstract class UserService {
    
        /** 校验密码
         * @author Sam
         * @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 "";
        }
    }
    
    
    • 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

    小结:因为声明抽象方法,所以整个类也必须声明为抽象类。 重点在 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);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    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) {
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    6. 综述

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

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

  • 相关阅读:
    实验室通风系统工程-全钢通风柜-实验室废气处理
    如果对区块链的呈现形态进行总结,虚拟化和数字化,无疑是最确切的注脚
    AVR128单片机 USART通信控制发光二极管显示
    【FFmpeg】学会添加水印,只要这一篇就足够
    几种常用的排序
    网络安全,下一个十年饭碗稳了!
    小红书电商运营实战课,从0打造全程实操(65节视频课)
    MySQL(5)
    Spring框架详解
    计算机毕业设计Java自习室座位预约管理(源码+系统+mysql数据库+lw文档)
  • 原文地址:https://blog.csdn.net/rothchil/article/details/126571538