• 浅析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 ,使得这些方法对外部客户端不可见。

  • 相关阅读:
    Oracle-job跑批变慢案例
    Influence Matters 成立印度尼西亚办公室,构建北亚及东南亚服务中心
    一个示例学习C语言到汇编层面
    Gateway入门
    串口收发UART(Verilog HDL)
    Perceptron, Support Vector Machine and Dual Optimization Problem (3)
    文档在线预览(五)在服务器部署组件来实现在线预览
    SSM之Spring注解式缓存Redis
    使用.NET简单实现一个Redis的高性能克隆版(六)
    已知有十六支男子足球队,参加2008 北京奥运会。写一个程序,把这16 支球队随机分为4 个组。
  • 原文地址:https://blog.csdn.net/rothchil/article/details/126571538