16.1 场景问题
16.1.1 登录控制
几乎所有的应用系统,都需要系统登录控制的功能,有些系统甚至有多个登录控制的功能,比如:普通用户可以登录前台,进行相应的业务操作;而工作人员可以登录后台,进行相应的系统管理或业务处理。
现在有这么一个基于Web的企业级应用系统,需要实现这两种登录控制,直接使用不同的登录页面来区分它们,把基本的功能需求分别描述如下:
先看看普通用户登录前台的登录控制的功能:
- 前台页面:用户能输入用户名和密码;提交登录请求,让系统去进行登录控制
- 后台:从数据库获取登录人员的信息
- 后台:判断从前台传递过来的登录数据,和数据库中已有的数据是否匹配
- 前台Action:如果匹配就转向首页,如果不匹配就返回到登录页面,并显示错误提示信息
再来看看工作人员登录后台的登录控制功能:
- 前台页面:用户能输入用户名和密码;提交登录请求,让系统去进行登录控制
- 后台:从数据库获取登录人员的信息
- 后台:把从前台传递过来的密码数据,使用相应的加密算法进行加密运算,得到加密后的密码数据
- 后台:判断从前台传递过来的用户名和加密后的密码数据,和数据库中已有的数据是否匹配
- 前台Action:如果匹配就转向首页,如果不匹配就返回到登录页面,并显示错误提示信息
说明:普通用户和工作人员在数据库里面是存储在不同表里面的;当然也是不同的模块来维护普通用户的数据和工作人员的数据;另外工作人员的密码是加密存放的。
16.1.2 不用模式的解决方案
由于普通用户登录和工作人员登录是不同的模块,有不同的页面,不同的逻辑处理,不同的数据存储,因此,在实现上完全当成两个独立的小模块去完成了。这里把它们的逻辑处理部分分别实现出来。
(1)先看普通用户登录的逻辑处理部分,示例代码如下:
/** * 普通用户登录控制的逻辑处理 */ public class NormalLogin { /** * 判断登录数据是否正确,也就是是否能登录成功 * @param lm 封装登录数据的Model * @return true表示登录成功,false表示登录失败 */ public boolean login(LoginModel lm) { //1:从数据库获取登录人员的信息,就是根据用户编号去获取人员的数据 UserModel um = this.findUserByUserId(lm.getUserId()); //2:判断从前台传递过来的登录数据,和数据库中已有的数据是否匹配 //先判断用户是否存在,如果um为null,说明用户肯定不存在 //但是不为null,用户不一定存在,因为数据层可能返回new UserModel(); //因此还需要做进一步的判断 if (um != null) { //如果用户存在,检查用户编号和密码是否匹配 if (um.getUserId().equals(lm.getUserId()) && um.getPwd().equals(lm.getPwd())) { return true; } } return false; } /** * 根据用户编号获取用户的详细信息 * @param userId 用户编号 * @return 对应的用户的详细信息 */ private UserModel findUserByUserId(String userId) { // 这里省略具体的处理,仅做示意,返回一个有默认数据的对象 UserModel um = new UserModel(); um.setUserId(userId); um.setName("test"); um.setPwd("test"); um.setUuid("User0001"); return um; } } |
对应的LoginModel,示例代码如下:
/** * 描述登录人员登录时填写的信息的数据模型 */ 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; } } |
对应的UserModel,示例代码如下:
/** * 描述用户信息的数据模型 */ public class UserModel { private String uuid,userId,pwd,name; 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; } } |
(2)再看看工作人员登录的逻辑处理部分,示例代码如下:
/** * 工作人员登录控制的逻辑处理 */ public class WorkerLogin { /** * 判断登录数据是否正确,也就是是否能登录成功 * @param lm 封装登录数据的Model * @return true表示登录成功,false表示登录失败 */ public boolean login(LoginModel lm) { //1:根据工作人员编号去获取工作人员的数据 WorkerModel wm = findWorkerByWorkerId(lm.getWorkerId()); //2:判断从前台传递过来的用户名和加密后的密码数据, //和数据库中已有的数据是否匹配 //先判断工作人员是否存在,如果wm为null,说明工作人员肯定不存在 //但是不为null,工作人员不一定存在, //因为数据层可能返回new WorkerModel();因此还需要做进一步的判断 if (wm != null) { //3:把从前台传来的密码数据,使用相应的加密算法进行加密运算 String encryptPwd = this.encryptPwd(lm.getPwd()); //如果工作人员存在,检查工作人员编号和密码是否匹配 if (wm.getWorkerId().equals(lm.getWorkerId()) && wm.getPwd().equals(encryptPwd)) { return true; } } return false; } /** * 对密码数据进行加密 * @param pwd 密码数据 * @return 加密后的密码数据 */ private String encryptPwd(String pwd){ //这里对密码进行加密,省略了 return pwd; } /** * 根据工作人员编号获取工作人员的详细信息 * @param workerId 工作人员编号 * @return 对应的工作人员的详细信息 */ private WorkerModel findWorkerByWorkerId(String workerId) { // 这里省略具体的处理,仅做示意,返回一个有默认数据的对象 WorkerModel wm = new WorkerModel(); wm.setWorkerId(workerId); wm.setName("Worker1"); wm.setPwd("worker1"); wm.setUuid("Worker0001"); return wm; } } |
对应的LoginModel,示例代码如下:
/** * 描述登录人员登录时填写的信息的数据模型 */ public class LoginModel{ private String workerId,pwd; public String getWorkerId() { return workerId; } public void setWorkerId(String workerId) { this.workerId = workerId; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } } |
对应的WorkerModel,示例代码如下:
/** * 描述工作人员信息的数据模型 */ public class WorkerModel { private String uuid,workerId,pwd,name; public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; } public String getWorkerId() { return workerId; } public void setWorkerId(String workerId) { this.workerId = workerId; } 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; } } |
16.1.3 有何问题
看了上面的实现示例,是不是很简单。但是,仔细看看,总会觉得有点问题,两种登录的实现太相似了,现在是完全分开,当作两个独立的模块来实现的,如果今后要扩展功能,比如要添加“控制同一个编号同时只能登录一次”的功能,那么两个模块都需要修改,是很麻烦的。而且,现在的实现中,也有很多相似的地方,显得很重复。另外,具体的实现和判断的步骤混合在一起,不利于今后变换功能,比如要变换加密算法等。
总之,上面的实现,有两个很明显的问题:一是重复或相似代码太多;二是扩展起来很不方便。
那么该怎么解决呢?该如何实现才能让系统既灵活又能简洁的实现需求功能呢?
相关推荐
模板模式定义模板模式,在Gof的《设计模式》中定义为:Define the skeleton of an algorithm in an operation,
策略模式结合模板方法模式的设计思路 策略模式结合模板方法模式是策略模式的一种变形,目的是为了解决策略模式中的一些共性问题。在策略模式中,经常会出现这样一种情况,就是发现这一系列算法的实现上存在公共功能...
模板方法模式是一种行为设计模式,它在面向对象编程中扮演着重要的角色。这种模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。这样使得子类可以在不改变算法结构的情况下,重新定义该算法的某些特定步骤...
1. **抽象模板(Abstract Class)**:这是模板模式的核心,包含一个模板方法,该方法定义了算法的基本步骤。同时,抽象模板类还可能包含一些具体方法,这些方法已经实现了算法的一部分。 2. **具体模板(Concrete ...
第十六章:模板方法模式一、豆浆制作问题编写制作豆浆的程序,说明如下:制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎通过添加不同的配料,可
1. **抽象类(Abstract Class)**:模板方法模式中的关键角色,它定义了一个操作中的算法框架,声明了将在子类中被重写的抽象方法和具体方法。抽象类通常包含一个模板方法,这个方法的实现会调用一些基本方法。 2. ...
1. **减少重复代码**:模板方法模式通过将公共行为集中在一个模板方法中,减少了重复代码的数量。 2. **易于扩展**:添加新的子类时只需要重写某些方法,而不需要改变现有的模板方法。 3. **提高可维护性**:由于...
1. **模式定义**:模板模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。它使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 2. **主要角色**: - **抽象类(Abstract Class)**:...
1. **抽象类(Abstract Class)**:这是模板模式的核心,它定义了模板方法以及一些具体方法。模板方法是一个具体方法,通常为final类型,以防止被子类重写。它定义了算法的主要结构,而将一些步骤留给了子类来实现。...
模板模式是一种行为设计模式,它使你能在代码中定义一个操作的不同步骤,并让子类决定这些步骤如何执行。模板模式提供了创建算法结构的通用接口,而具体的实现则由子类来完成。这种模式允许在不修改原有代码的情况下...
1.1 动机 1.2 讲解 1.3 模式定义 1.4 结构 1.5 要点总结
Java模板模式和策略模式是两种常用的面向对象设计模式,它们在软件开发中有着广泛的应用。模板模式是一种行为设计模式,而策略模式则属于结构型设计模式。这两种模式都是用来处理算法和行为的,但它们的核心理念和...
1. 封装变化:模板模式将不变的部分封装到抽象类中,而易变的部分则由子类去实现。 2. 提高代码复用:通过定义模板方法,可以避免代码重复,提高代码复用性。 3. 结构清晰:定义了算法的框架,使得算法的结构清晰,...
**模板模式(Template Pattern)**是一种行为设计模式,它使你能在抽象类中定义操作算法的框架,而将一些步骤延迟到子类中。这样,子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 在Java、C#等面向...
1. **抽象类(AbstractClass)**:这个类定义了模板方法,并可能包含一些具体方法。模板方法通常是一个最终方法(final),防止被子类覆盖。抽象方法由子类实现,提供具体的算法步骤。 2. **具体类(ConcreteClass...
回调函数和模板模式都是软件设计中用于实现代码复用和扩展的重要工具,它们在不同的场景下各有优势。模板模式是一种行为设计模式,它定义了一组操作的算法骨架,同时允许子类在某些步骤中替换具体行为。而回调则是...
1. **多步骤处理**:当一个业务流程包含多个固定步骤时,可以使用模板方法模式来定义这些步骤的顺序。 2. **算法的框架**:当需要定义一个算法的骨架,而将算法的某些步骤留给子类实现时,可以使用此模式。 3. *...
模板模式遵循“开闭原则”,即对扩展开放,对修改关闭。它通过定义一个操作中的算法框架,将具体步骤留给子类来实现。这种模式允许在不改动原有代码的情况下,通过继承来拓展功能,提高了代码的可复用性和可扩展性。...
1. **抽象类(Abstract Class)**: 定义了模板方法和一些基本操作。模板方法通常是一个final方法,它调用了一系列的步骤,这些步骤可以是抽象的或具体的方法。抽象方法需要子类去实现,而具体方法则提供了默认的行为...