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

目录

场景

原有逻辑

有何问题

解决方案

解决思路 

代码实现 

重写示例

模板方法的优缺点

模板方法的本质 

何时选用


场景

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

原有逻辑

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

有何问题

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

解决方案

模板方法

定义:

解决思路 

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

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

研磨设计模式day14模板方法模式_第1张图片

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

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

代码实现 

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

package day14模板方法模式;

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

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


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

具体实现

package day14模板方法模式;

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

    @Override
    public void doPrimitiveOperation2() {

    }
}

重写示例

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

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;
    }

}

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

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;
    }
}

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

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;
    }
}

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

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

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);
    }
}

研磨设计模式day14模板方法模式_第2张图片

模板方法的优缺点

研磨设计模式day14模板方法模式_第3张图片

模板方法的本质 

固定算法骨架

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

研磨设计模式day14模板方法模式_第4张图片

何时选用

研磨设计模式day14模板方法模式_第5张图片

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