23种设计模式之模板方法模式(模板模式)
文章目录
- 23种设计模式之模板方法模式(模板模式)
- 设计思想
- 模板方法的优缺点
- 模板方法模式的缺点
- 代码解析
- 小结
设计思想
原文:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
以上原文,我们可以抠出几个关键字
- 算法的骨架
- 些许步骤延迟到子类
- 算法结构不可变
- 重定义特定步骤
以上四点是我个人觉得比较重要的点,我们先模拟去上班的场景,早上需要去上班那么肯定是有这几个选项的
①:洗脸刷牙
②:出行交通工具的选择
③:选择上班路线
以上三点就是我们的去上班需要干的事,我们可以将这三件事当成算法的骨架,随后我们可以将第②和第③这两个步骤延迟到子类(将实现交给子类)。看到关键字三,算法结构不可变,其实也就是说整个去上班的步骤顺序不可变化,关键字四重定义特定步骤,思考一下起床洗脸刷牙基本固定(不要抬杠)只有步骤②和③是多变的,有可能你选择坐公交但是每一辆公交路线是不一致的,所以我们可以将这些步骤交给子类是实现。
模板方法的优缺点
模板方法模式的优点
- 算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改。
- 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用。
- 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现。
- 提供了一个基本框架,容易扩展子类。模板方法有框架控制如何做事情,而由使用框架的人指定框架算法中每个步骤的细节。子 类只要继承父类,实现抽象方法,就可以使用父类的算法。
模板方法模式的缺点
- 类数目的增加:每一个抽象类都需要一个子类来实现,这样导致类的个数增加。
- 类数量的增加导致系统实现的复杂度提高。
- 继承关系的缺点:如果父类添加新的抽象方法,所有子类都要改一遍。
模板方法模式的实际应用
在实际的开发中,有一些常用的框架和库使用了模板方法(Template Method)设计模式,以下是其中的几个例子:
Servlet:Servlet 是 JavaEE 中常用的 Web 开发框架,它使用了模板方法设计模式来处理 HTTP 请求和响应。在 Servlet 中,抽象类 HttpServlet 定义了模板方法 service(),子类需要继承 HttpServlet 并重写 service() 方法来处理具体的请求和生成响应。
Spring Framework:Spring 是一个广泛使用的应用程序开发框架,其中的一些子框架也使用了模板方法设计模式。比如,在 Spring Web MVC 框架中,HandlerInterceptor 接口定义了多个模板方法,如 preHandle()、postHandle() 和 afterCompletion(),用于处理请求拦截和后置处理等操作。
Hibernate 框架:Hibernate 是一个用于对象关系映射(ORM)的框架,它使用了模板方法设计模式来定义数据库访问的基本骨架。比如,在 Hibernate 中,Session 是一个抽象类,它定义了一系列的模板方法,如 save()、update() 和 delete(),用于执行数据库操作。
Android 开发中的 Activity 和 Fragment:在 Android 开发中,Activity 和 Fragment 是常用的组件,它们在生命周期管理和用户交互等方面使用了模板方法设计模式。比如,在 Activity 中,onCreate()、onStart() 和 onDestroy() 等方法作为模板方法,开发人员可以重写这些方法来提供自己的业务逻辑。
代码解析
//抽象类
public abstract class Work {/*** 定义模板方法*/public final void goToWork(String name) {System.out.println(name + "起床了");System.out.println(name + "叠被子了");System.out.println(name + "刷牙了");System.out.println(name + "洗脸了");System.out.println(name + "开始选择座驾");this.rideVehicle();System.out.println("以选择以下行驶路线");this.selectPath();}/*** 乘坐交通工具*/abstract void rideVehicle();/*** 选择路线*/abstract void selectPath();
}
/员工A
public class StaffA extends Work {void rideVehicle() {System.out.println("乘坐五菱宏光");}void selectPath() {System.out.println("无拥堵情况,却距离较远");}}
//员工B
public class StaffB extends Work {void rideVehicle() {System.out.println("乘坐劳斯莱斯幻影");}void selectPath() {System.out.println("拥堵却距离较近的路线");}
}
public class Test {public static void main(String[] args) {StaffA staffA = new StaffA();staffA.goToWork("王思葱");}
}
public class Test {public static void main(String[] args) {StaffB staffB = new StaffB();staffB.goToWork("王思冲");}
}
小结
分别运行StaffA以及StaffB这两个类我们可以看到整个的步骤顺序是没有变的,只有交通工具以及路线发生了变化,个人认为代码已经诠释了模板模式的精髓,我们平时出现多个类似的功能功能点比如解析DOC文件或者XLSX等不同的文件,前期一些初始化的操作可以封装到模板方法中,到了具体解析哪一种类型的文件,再去交给子类实现。我们可以自己去想一些场景,通过编码增强自己对该模式的理解。
模板模式相对比较简单一些吧,希望能够领悟到我列举的四个关键词条,早日使用到实际项目中。