16.2 解决方案
16.2.1 模板方法模式来解决
用来解决上述问题的一个合理的解决方案就是模板方法模式。那么什么是模板方法模式呢?
(1)模板方法模式定义
(2)应用模板方法模式来解决的思路
仔细分析上面的问题,重复或相似代码太多、扩展不方便,出现这些问题的原因在哪里?主要就是两个实现是完全分开、相互独立的,没有从整体上进行控制。如果把两个模块合起来看,就会发现,那些重复或相似的代码就应该被抽取出来,做成公共的功能,而不同的登录控制就可以去扩展这些公共的功能。这样一来,扩展的时候,如果出现有相同的功能,那就直接扩展公共功能就可以了。
使用模板方法模式,就可以很好的来实现上面的思路。分析上面两个登录控制模块,会发现它们在实现上,有着大致相同的步骤,只是在每步具体的实现上,略微有些不同,因此,可以把这些运算步骤看作是算法的骨架,把具体的不同的步骤实现,延迟到子类去实现,这样就可以通过子类来提供不同的功能实现了。
经过分析总结,登录控制大致的逻辑判断步骤如下:
- 根据登录人员的编号去获取相应的数据
- 获取对登录人员填写的密码数据进行加密后的数据,如果不需要加密,那就是直接返回登录人员填写的密码数据
- 判断登录人员填写的数据和从数据库中获取的数据是否匹配
在这三个步骤里面,第一个和第三个步骤是必不可少的,而第二个步骤是可选的。那么就可以定义一个父类,在里面定义一个方法来定义这个算法骨架,这个方法就是模板方法,然后把父类无法确定的实现,延迟到具体的子类来实现就可以了。
通过这样的方式,如果要修改加密的算法,那就在模板的子类里面重新覆盖实现加密的方法就好了,完全不需要去改变父类的算法结构,就可以重新定义这些特定的步骤。
16.2.2 模式结构和说明
模板方法模式的结构如图16.1所示:
图16.1 模板方法模式的结构示意图
AbstractClass:
抽象类。用来定义算法骨架和原语操作,具体的子类通过重定义这些原语操作来实现一个算法的各个步骤。在这个类里面,还可以提供算法中通用的实现。
ConcreteClass:
具体实现类。用来实现算法骨架中的某些步骤,完成跟特定子类相关的功能。
16.2.3 模板方法模式示例代码
(1)先来看看AbstractClass的写法,示例代码如下:
/** * 定义模板方法、原语操作等的抽象类 */ public abstract class AbstractClass { /** * 原语操作1,所谓原语操作就是抽象的操作,必须要由子类提供实现 */ public abstract void doPrimitiveOperation1(); /** * 原语操作2 */ public abstract void doPrimitiveOperation2(); /** * 模板方法,定义算法骨架 */ public final void templateMethod() { doPrimitiveOperation1(); doPrimitiveOperation2(); } } |
(2)再看看具体实现类的写法,示例代码如下:
/** * 具体实现类,实现原语操作 */ public class ConcreteClass extends AbstractClass { public void doPrimitiveOperation1() { //具体的实现 } public void doPrimitiveOperation2() { //具体的实现 } } |
16.2.4 使用模板方法模式重写示例
要使用模板方法模式来实现前面的示例,按照模板方法模式的定义和结构,需要定义出一个抽象的父类,在这个父类里面定义模板方法,这个模板方法应该实现进行登录控制的整体的算法步骤。当然公共的功能,就放到这个父类去实现,而这个父类无法决定的功能,就延迟到子类去实现。
这样一来,两种登录控制就做为这个父类的子类,分别实现自己需要的功能。此时系统的结构如图16.2所示:
图16.2 使用模板方法模式实现示例的结构示意图
(1)为了把原来的两种登录控制统一起来,首先需要把封装登录控制所需要的数据模型统一起来,不再区分是用户编号还是工作人员编号,而是统一称为登录人员的编号,还有把其它用不上的数据去掉,这样就直接使用一个数据模型就可以了。当然,如果各个子类实现需要其它的数据,还可以自行扩展。示例代码如下:
/** * 封装进行登录控制所需要的数据 */ 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; } } |
(2)接下来定义公共的登录控制算法骨架,示例代码如下:
/** * 登录控制的模板 */ public abstract class LoginTemplate { /** * 判断登录数据是否正确,也就是是否能登录成功 * @param lm 封装登录数据的Model * @return true表示登录成功,false表示登录失败 */ public final boolean login(LoginModel lm){ //1:根据登录人员的编号去获取相应的数据 LoginModel dbLm = this.findLoginUser(lm.getLoginId()); if(dbLm!=null){ //2:对密码进行加密 String encryptPwd = this.encryptPwd(lm.getPwd()); //把加密后的密码设置回到登录数据模型里面 lm.setPwd(encryptPwd); //3:判断是否匹配 return this.match(lm, dbLm); } return false; } /** * 根据登录编号来查找和获取存储中相应的数据 * @param loginId 登录编号 * @return 登录编号在存储中相对应的数据 */ public abstract LoginModel findLoginUser(String loginId); /** * 对密码数据进行加密 * @param pwd 密码数据 * @return 加密后的密码数据 */ public String encryptPwd(String pwd){ return pwd; } /** * 判断用户填写的登录数据和存储中对应的数据是否匹配得上 * @param lm 用户填写的登录数据 * @param dbLm 在存储中对应的数据 * @return true表示匹配成功,false表示匹配失败 */ public boolean match(LoginModel lm,LoginModel dbLm){ if(lm.getLoginId().equals(dbLm.getLoginId()) && lm.getPwd().equals(dbLm.getPwd())){ return true; } return false; } } |
(3)实现新的普通用户登录控制的逻辑处理,示例代码如下:
/** * 普通用户登录控制的逻辑处理 */ public class NormalLogin extends LoginTemplate{ public LoginModel findLoginUser(String loginId) { // 这里省略具体的处理,仅做示意,返回一个有默认数据的对象 LoginModel lm = new LoginModel(); lm.setLoginId(loginId); lm.setPwd("testpwd"); return lm; } } |
(4)实现新的工作人员登录控制的逻辑处理,示例代码如下:
/** * 工作人员登录控制的逻辑处理 */ public class WorkerLogin extends LoginTemplate{ public LoginModel findLoginUser(String loginId) { // 这里省略具体的处理,仅做示意,返回一个有默认数据的对象 LoginModel lm = new LoginModel(); lm.setLoginId(loginId); lm.setPwd("workerpwd"); return lm; }
public String encryptPwd(String pwd){ //覆盖父类的方法,提供真正的加密实现 //这里对密码进行加密,比如使用:MD5、3DES等等,省略了 System.out.println("使用MD5进行密码加密"); return pwd; } } |
通过上面的示例,可以看出来,把原来的实现改成使用模板方法模式来实现,也并不困难,写个客户端测试一下,以便更好的体会,示例代码如下:
public class Client { public static void main(String[] args) { //准备登录人的信息 LoginModel lm = new LoginModel(); lm.setLoginId("admin"); lm.setPwd("workerpwd");
//准备用来进行判断的对象 LoginTemplate lt = new WorkerLogin(); LoginTemplate lt2 = new NormalLogin();
//进行登录测试 boolean flag = lt.login(lm); System.out.println("可以登录工作平台="+flag);
boolean flag2 = lt2.login(lm); System.out.println("可以进行普通人员登录="+flag2); } } |
运行结果示例如下:
使用MD5进行密码加密 可以登录工作平台=true 可以进行普通人员登录=false |
当然,你可以使用不同的测试数据来测试这个示例。
相关推荐
策略模式结合模板方法模式的设计思路 策略模式结合模板方法模式是策略模式的一种变形,目的是为了解决策略模式中的一些共性问题。在策略模式中,经常会出现这样一种情况,就是发现这一系列算法的实现上存在公共功能...
模板方法模式是一种行为设计模式,它在面向对象编程中扮演着重要的角色。这种模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。这样使得子类可以在不改变算法结构的情况下,重新定义该算法的某些特定步骤...
模板模式是一种行为设计模式,它在Java编程中扮演着重要的角色,主要用来定义算法的骨架,而将一些步骤延迟到子类中。这种模式让子类可以在不改变算法整体结构的情况下,重定义某些特定步骤。在Java设计模式之模板...
模板方法模式是设计模式中行为模式的一种,它在软件开发中起到了重要的作用,尤其是在复杂的系统设计中。模板方法模式遵循“开闭原则”,允许我们定义一个算法的骨架,同时允许子类在不改变整体结构的情况下,对算法...
### 设计模式之模板方法模式解析 #### 一、引言 在软件开发过程中,我们经常面临这样的场景:有一些步骤是固定的,而某些步骤则可能因具体实现而异。为了解决这类问题,设计模式中引入了一种叫做“模板方法模式”的...
模板模式是一种行为设计模式,它在面向对象编程中扮演着重要的角色。这个模式定义了算法的骨架,并允许子类在不改变结构的情况下重定义某些步骤。模板方法模式遵循了“开闭原则”,即对扩展开放,对修改关闭,使得...
模板模式是一种行为设计模式,它在面向对象编程中扮演着重要的角色。此模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。这样,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤...
模板模式是一种行为设计模式,它使你能在代码中定义一个操作的不同步骤,并让子类决定这些步骤如何执行。模板模式提供了创建算法结构的通用接口,而具体的实现则由子类来完成。这种模式允许在不修改原有代码的情况下...
Java模板模式和策略模式是两种常用的面向对象设计模式,它们在软件开发中有着广泛的应用。模板模式是一种行为设计模式,而策略模式则属于结构型设计模式。这两种模式都是用来处理算法和行为的,但它们的核心理念和...
模板模式是一种行为设计模式,它使你能在不破坏封装性的前提下,定义对象间的一系列基本操作,并在子类中实现这些操作的具体步骤。在模板模式中,一个抽象类公开定义了执行它的方法的方式,而将具体实现延迟到子类中...
**模板模式(Template Pattern)**是一种行为设计模式,它使你能在抽象类中定义操作算法的框架,而将一些步骤延迟到子类中。这样,子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 在Java、C#等面向...
模板方法模式是一种行为设计模式,它允许在定义算法框架的同时,允许子类为一个或多个步骤提供具体的实现。这种模式通常用于代码复用,尤其是在有多种算法相似的情况下,通过抽象出公共部分,让子类专注于具体步骤的...
### 深入浅出设计模式之模板方法模式 #### 一、模板方法模式概述 设计模式是软件工程中一种非常重要的技术手段,它能够帮助我们解决常见的编程问题,并提高代码的可重用性、可扩展性和可维护性。模板方法模式是一...
模板模式遵循“开闭原则”,即对扩展开放,对修改关闭。它通过定义一个操作中的算法框架,将具体步骤留给子类来实现。这种模式允许在不改动原有代码的情况下,通过继承来拓展功能,提高了代码的可复用性和可扩展性。...
模板方法模式是设计模式中的一种行为模式,它在软件工程中扮演着重要的角色,尤其是在C++这样的面向对象编程语言中。这种模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的...
2. 模板方法(TemplateMethod):这是核心方法,定义了算法的整体结构,调用了抽象方法和具体方法。 3. 具体方法(ConcreteMethod):这些方法在抽象类中已经完全实现,子类不需要关心这部分代码。 例如,假设我们...
回调函数和模板模式都是软件设计中用于实现代码复用和扩展的重要工具,它们在不同的场景下各有优势。模板模式是一种行为设计模式,它定义了一组操作的算法骨架,同时允许子类在某些步骤中替换具体行为。而回调则是...
模板方法模式是设计模式中行为型模式的一种,它在软件工程中扮演着非常重要的角色,尤其是在Java编程中。模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。它允许子类不改变一个算法的结构即可重...
处理层的设计采用了设计模式中的策略模式、模板方法模式和工厂模式。 Server端和Client端的实现也采用了分层的设计方式,包含自定义的模型层、视图层和控制层。 说明:程序采用配置文件的方式进行初始化,运行时时请...