设计模式之模板方法模式

例子:登陆(普通用户,工作人员)
设计模式之模板方法模式_第1张图片

设计模式之模板方法模式_第2张图片

没有使用设计模式实现用户登陆

package com.tao.YanMoDesignPattern.template.notPattern;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description
 * @Version 1.0
 **/
public class LoginModel {

    private String userId,pwd;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPwd() {
        return pwd;
    }

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

package com.tao.YanMoDesignPattern.template.notPattern;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description 普通用户登陆控制的逻辑处理
 * @Version 1.0
 **/
public class NormalLogin {

    public boolean login(LoginModel lm){
        // 1、先从数据库获取登陆人员的信息
        UserModel um = this.findUserByUserId(lm.getUserId());

        // 2、判断从前台传递过来的登陆数据和数据库中已有的数据是否匹配
        // 判断用户是否存在,如果是null,说明用户肯定不存在
        if (um != null){
            if (um.getUserId().equals(lm.getUserId())&&um.getPwd().equals(lm.getPwd())){
                return true;
            }
            return false;
        }
        return false;
    }

    private UserModel findUserByUserId(String userId) {
        // 这里省略具体的处理,返回一个默认的数据对象
        UserModel model = new UserModel();
        model.setUserId(userId);
        model.setName("test");
        model.setPwd("User001");
        model.setUuid("1231456");
        return model;
    }
}

package com.tao.YanMoDesignPattern.template.notPattern;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description
 * @Version 1.0
 **/
public class UserModel {
    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getPwd() {
        return pwd;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String uuid,userId,pwd,name;
}

package com.tao.YanMoDesignPattern.template.notPattern;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description 普通用户登陆控制的逻辑处理
 * @Version 1.0
 **/
public class WorkerLogin {

    public boolean login(WorkerModel lm){
        // 1、先从数据库获取登陆人员的信息
        WorkerModel wm = findWorkerByWorkerId(lm.getWorkId());

        // 2、判断从前台传递过来的登陆数据和数据库中已有的数据是否匹配
        // 判断用户是否存在,如果是null,说明用户肯定不存在
        if (wm != null){
            if (wm.getWorkId().equals(lm.getWorkId())&&wm.getPwd().equals(enctyptPwd(lm.getPwd()))){
                return true;
            }
            return false;
        }
        return false;
    }

    private WorkerModel findWorkerByWorkerId(String workId) {
        WorkerModel workerModel = new WorkerModel();
        workerModel.setWorkId("work001");
        workerModel.setPwd("pwdWork1");
        workerModel.setName("workName");
        workerModel.setUuid("123124124");
        return workerModel;
    }

    private String enctyptPwd(String pwd){
        // 加密,省略
        return pwd;
    }



}

package com.tao.YanMoDesignPattern.template.notPattern;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description
 * @Version 1.0
 **/
public class WorkerModel {
    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getWorkId() {
        return workId;
    }

    public void setWorkId(String workId) {
        this.workId = workId;
    }

    public String getPwd() {
        return pwd;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String uuid,workId,pwd,name;
}

标准的模板方法模式*

package com.tao.YanMoDesignPattern.template.pattern;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description 定义模板方法,源语操作等的抽象类
 * @Version 1.0
 **/
public abstract class AbstractClass {

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

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

    /**
     * 模板方法,定义算法骨架
     */
    public final void templateMethod(){
        doPrimitiveOperation1();
        doPrimitiveOperation2();
    }
}

package com.tao.YanMoDesignPattern.template.pattern;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description
 * @Version 1.0
 **/
public class ConcreteClass extends AbstractClass{
    @Override
    public void doPrimitiveOperation1() {
        // 具体的实现
    }

    @Override
    public void doPrimitiveOperation2() {
        // 具体的实现
    }
}

使用模板实现以上用户登陆场景

package com.tao.YanMoDesignPattern.template.case1_extend;


/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description
 * @Version 1.0
 **/
public class NormalLoginModel extends LoginModel {

    private String question,answer;

    public String getQuestion() {
        return question;
    }

    public void setQuestion(String question) {
        this.question = question;
    }

    public String getAnswer() {
        return answer;
    }

    public void setAnswer(String answer) {
        this.answer = answer;
    }
}

核心方法

package com.tao.YanMoDesignPattern.template.case1_extend;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description
 * @Version 1.0
 **/
public abstract class LoginTemplate {

    /**
     * 判断登录数据是否正确,也就是是否能登陆成功
     *
     * @param lm lm 封装登陆数据的Model
     * @return boolean
     */
    public final boolean Login(LoginModel lm){
        // 1、根据登陆人员的编号去查找
        LoginModel dbLm = this.findLoginUser(lm.getLoginId());
        if (dbLm != null){
            // 加密
            String encrytPwd = this.encryptPwd(lm.getPwd());
            // 把加密后的密码设置回到登陆数据模型中
            lm.setPwd(encrytPwd);
            // 判断是否匹配
            return this.match(lm, dbLm);
        }
        return false;
    }

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

    /**
     * 加密pwd
     *
     * @param pwd
     * @return 加密后的密码数据
     */
    private String encryptPwd(String pwd) {
        return pwd;
    }

    public abstract LoginModel findLoginUser(String loginId) ;
}

package com.tao.YanMoDesignPattern.template.case1_extend;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description
 * @Version 1.0
 **/
public class NormalLogin extends LoginTemplate{
    @Override
    public LoginModel findLoginUser(String loginId) {
        // 省略具体操作,返回一个默认数据对象
        NormalLoginModel lm = new NormalLoginModel();
        lm.setLoginId(loginId);
        lm.setPwd("workpwd");
        return lm;
    }
}

package com.tao.YanMoDesignPattern.template.case1_extend;

/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description 工作人员登录
 * @Version 1.0
 **/
public class WorkerLogin extends LoginTemplate{
    @Override
    public LoginModel findLoginUser(String loginId) {
        // 省略具体操作,返回一个默认数据对象
        NormalLoginModel lm = new NormalLoginModel();
        lm.setLoginId(loginId);
        lm.setPwd("workpwd");
        return lm;
    }

    public String encryptPwd(String pwd){
        // 覆盖弗雷方法,提供真正的加密
        System.out.println("使用MD5 加密");
        return pwd;
    }
}

测试

package com.tao.YanMoDesignPattern.template.case1_extend;



/**
 * @Author Mi_Tao
 * @Date 2023/7/22
 * @Description
 * @Version 1.0
 **/
public class Client {

    public static void main(String[] args) {
        // 准备登陆人信息
        NormalLoginModel nlm = new NormalLoginModel();
        nlm.setPwd("testpwd");
        nlm.setLoginId("testUser");
        nlm.setQuestion("testQuestion");
        nlm.setAnswer("testAnswer");

        // 准备用来进行判断的对象
        LoginTemplate lt3 = new NormalLogin2();

        // 登录测试
        boolean login = lt3.Login(nlm);
        System.out.println("可以进行普通人员加强版登陆="+login);

    }
}

设计模式之模板方法模式_第3张图片

Tips:
既要约束子类的行为,又要为子类提供公共功能的时候使用抽象类。

设计模式之模板方法模式_第4张图片

Java回调与模板方法模式
设计模式之模板方法模式_第5张图片
实现模板方法的两种方式
设计模式之模板方法模式_第6张图片
模板方法模式的优缺点
设计模式之模板方法模式_第7张图片

什么时候使用模板方法模式
设计模式之模板方法模式_第8张图片
相关模式
设计模式之模板方法模式_第9张图片

以上内容参考《研磨设计模式》
例子源码: https://gitee.com/zitaoyang/design-mode.git

你可能感兴趣的:(设计模式,设计模式,模板方法模式,数据库)