研磨设计模式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);
    }
}

模板方法的优缺点

模板方法的本质

固定算法骨架

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

何时选用

相关推荐
J_liaty1 天前
23种设计模式一代理模式
设计模式·代理模式
苏渡苇1 天前
优雅应对异常,从“try-catch堆砌”到“设计驱动”
java·后端·设计模式·学习方法·责任链模式
短剑重铸之日1 天前
《设计模式》第十一篇:总结
java·后端·设计模式·总结
feasibility.1 天前
AI 编程助手进阶指南:从 Claude Code 到 OpenCode 的工程化经验总结
人工智能·经验分享·设计模式·自动化·agi·skills·opencode
BD_Marathon1 天前
七大设计原则介绍
设计模式
YigAin1 天前
Unity23种设计模式之 享元模式
设计模式·享元模式
范纹杉想快点毕业2 天前
实战级ZYNQ中断状态机FIFO设计
java·开发语言·驱动开发·设计模式·架构·mfc
茂桑2 天前
DDD领域驱动设计-基础设施层
设计模式·架构
小温冲冲2 天前
通俗且全面精讲工厂设计模式
设计模式
进击的小头2 天前
设计模式与C语言高级特性的结合
c语言·设计模式