研磨设计模式day14模板方法模式

目录

场景

原有逻辑

有何问题

解决方案

解决思路

代码实现

重写示例

模板方法的优缺点

模板方法的本质

何时选用


场景

现在模拟一个场景,两个人要登录一个系统,一个是管理员一个是用户,这两个不同身份的登录是由后端对应的两个接口实现的,用户登录只需验证库里是否存在,管理员登录时需要验证加密后的密码是否与数据库数据一致。

原有逻辑

这里大致说一下,创建了两个实体用来描述用户和管理员传来的用户名、密码。创建两个模块来分别处理用户和管理员的登录。

有何问题

1.重复或相似代码太多2.扩展不方便(比如要添加同一个编号同时只能登录一次,那这两个登录模块都要修改)

解决方案

模板方法

定义:

解决思路

重复代码多、扩展不方便的原因在哪?就是因为没把那些相似的代码抽取出来做成公共的功能。

我们把具体的不同的步骤实现延迟到子类去实现,这样就可以通过子类来提供不同的功能实现了。

第一和第三个步骤是必不可少,第二个是可选的(可变的)。

先定义一个父类,并在内部提供一个方法来定义整个骨架。这个方法就是模板方法,然后把父类无法确定的实现,延迟到具体的子类来实现

代码实现

肯定有一个携带了骨架方法的父类,不用想肯定是抽象类

java 复制代码
package day14模板方法模式;

public abstract class AbstractClass {
    /**
     * 原语操作1,所谓原语操作就是抽象的操作,必须要由子类提供实现
     */
    public abstract void doPrimitiveOperation1();

    /**
     * 原语操作2,所谓原语操作就是抽象的操作,必须要由子类提供实现
     */
    public abstract void doPrimitiveOperation2();


    /**
     * 模板方法
     */
    public final void templateMethod(){
        doPrimitiveOperation1();
        doPrimitiveOperation2();
    }
}

具体实现

java 复制代码
package day14模板方法模式;

/**
 * 具体实现类,实现原语操作
 */
public class ConcreteClass extends AbstractClass{
    @Override
    public void doPrimitiveOperation1() {
        
    }

    @Override
    public void doPrimitiveOperation2() {

    }
}

重写示例

我们要实现登录的合并,首先需要一个共同的参数接收类

java 复制代码
package day14模板方法模式;

/**
 * 封装进行登录控制所需要的数据
 */
public class LoginModel {
    /**
     * 登陆人员的编号,通用的,可能是用户也可能是管理员
     */
    private String loginId;

    /**
     * 登录的密码
     */
    private String pwd;

    public String getLoginId() {
        return loginId;
    }

    public void setLoginId(String loginId) {
        this.loginId = loginId;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

}

接下来定义公共的登录控制算法骨架

java 复制代码
package day14模板方法模式;

/**
 * 登录控制的模板
 */
public abstract class LoginTemplate {
   public final boolean login(LoginModel lm){
       LoginModel loginUser = this.findLoginUser(lm.getLoginId());
       if (loginUser != null){
           String pwd = this.encryptPwd(lm.getPwd());
           lm.setPwd(pwd);
           // 判断是否匹配的上
           return this.match(lm,loginUser);
       }
       return false;
   }

    public boolean match(LoginModel lm, LoginModel loginUser){
       if (lm.getLoginId().equals(loginUser.getLoginId()) && lm.getPwd().equals(loginUser.getPwd())){
           return true;
       }
       return false;
    }

    /**
     * 根据登陆编号来查找和获取存储中相应的数据
     * @param loginId
     * @return
     */
   public abstract LoginModel findLoginUser(String loginId);

    /**
     * 对密码数据进行加密
     */
    public String encryptPwd(String pwd){
        return pwd;
    }
}

实现用户登录控制的逻辑处理

java 复制代码
package day14模板方法模式;

/**
 * 普通用户登录控制的逻辑处理
 */
public class NormalLogin extends LoginTemplate {
    @Override
    public LoginModel findLoginUser(String loginId) {
        // 这里省略具体的处理,仅作示意,返回一个有默认数据的对象
        LoginModel loginModel = new LoginModel();
        loginModel.setLoginId(loginId);
        loginModel.setPwd("testPwd");
        return loginModel;
    }
}

管理员登录控制的逻辑处理

java 复制代码
package day14模板方法模式;

/**
 * 工作人员登录控制的逻辑处理
 */
public class WorkerLogin extends LoginTemplate {
    @Override
    public LoginModel findLoginUser(String loginId) {
        // 这里省略具体的处理,仅作示意,返回一个有默认数据的对象
        LoginModel loginModel = new LoginModel();
        loginModel.setLoginId(loginId);
        loginModel.setPwd("testPwd");
        return loginModel;
    }

    @Override
    public String encryptPwd(String pwd) {
        System.out.println("使用MD5加密");
        return super.encryptPwd(pwd);
    }
}

Client

java 复制代码
package day14模板方法模式;

public class Client {
    public static void main(String[] args) {
        // 准备登陆人的信息
        LoginModel loginModel = new LoginModel();
        loginModel.setLoginId("admin");
        loginModel.setPwd("workerpwd");

        // 准备用来判断的对象
        WorkerLogin workerLogin = new WorkerLogin();
        NormalLogin normalLogin = new NormalLogin();

        // 进行登录测试
        boolean login = workerLogin.login(loginModel);
        System.out.println("管理员可以登录= " + login);

        boolean login1 = normalLogin.login(loginModel);
        System.out.println("用户可以登录=" + login1);
    }
}

模板方法的优缺点

模板方法的本质

固定算法骨架

很好的体现了开闭原则和里氏替换原则

何时选用

相关推荐
崎岖Qiu4 小时前
【设计模式笔记17】:单例模式1-模式分析
java·笔记·单例模式·设计模式
安冬的码畜日常9 小时前
【JUnit实战3_27】第十六章:用 JUnit 测试 Spring 应用:通过实战案例深入理解 IoC 原理
spring·观察者模式·设计模式·单元测试·ioc·依赖注入·junit5
她说彩礼65万11 小时前
C#设计模式 单例模式实现方式
单例模式·设计模式·c#
安冬的码畜日常14 小时前
【JUnit实战3_28】第十七章:用 JUnit 5 实测 SpringBoot 项目
spring boot·功能测试·测试工具·设计模式·单元测试·junit5
围巾哥萧尘15 小时前
TRAE Agent 歌曲创作助手构建与使用教程🧣
设计模式
superman超哥15 小时前
仓颉语言中流式I/O的设计模式深度剖析
开发语言·后端·设计模式·仓颉
m0_7482480216 小时前
Spring设计模式刨根问底
java·spring·设计模式
不要额外加糖18 小时前
tql,寥寥几行,实现无队列无感刷新
前端·javascript·设计模式
ACGkaka_18 小时前
设计模式学习(十二)状态模式
学习·设计模式·状态模式
乐悠小码19 小时前
Java设计模式精讲---01工厂方法模式
java·设计模式·工厂方法模式