一、概述
模版的原意是指:带着镂空文字的塑料板,只要用笔在模版的镂空处进行临摹,即可写出整齐的文字,此时无论谁来写都只要按着模版来使用,都可以写出要求的文字,在java中这种模式就转变为模版模式,只需在父类中使用抽象方法来处理执行的逻辑,此时忽略具体的执行任务。
Java中的定义:在父类中定义处理流程的框架,在子类中实现具体处理的模式称之为 Temple Method,也就是我们本章虽介绍的主题:
二、模式分析
其实这种模版的设计模式,我们在开发中其实经常会用到,基本每个出现抽象类的地方,都是这种模式的使用。
- 抽象类:从上面的叙述中可以了解,首先需要一个确定处理流程的抽象类,在其中通过方法的调用确定方法的执行逻辑和顺序
- 抽象方法:设定抽象方法用于具体的子类去实现真正的业务
- 子类:继承抽象类,重写其中的抽象方法,添加真正的处理逻辑
三、示例代码
现在我们通过一个简单的代码程序来使用一下模版模式,我们现在用这个模式来表述一个公司的员工到公司一天所做的事,将每个人到公司的事情大致分为:
- 进入公司
- 准备工作
- 打开电脑
- 工作
- 关电脑
- 回家
我们按照上面的分析,首先创建一个抽象类,代码如下:
abstract class AbstractDisplay {
protected abstract fun comingCompany()
protected abstract fun work()
protected abstract fun leaveCompany()
protected abstract fun prepare()
private fun openComputer() {
Log.e("=====", "打来了电脑!")
}
private fun closeComputer() {
Log.e("=====", "关闭了电脑!")
}
fun showWork() {
comingCompany()
prepare()
openComputer()
work()
closeComputer()
leaveCompany()
}
}
在上述的抽象类中,我们声明了几个抽象方法,在showWork()方法中,按照顺序调用了方法,现在创建具体的类来继承抽象类:
- 男员工:
class ManWorker(var name:String):AbstractDisplay() {
override fun prepare() {
Log.e("=====","泡个咖啡!")
}
override fun comingCompany() {
Log.e("=====","8点 开车到公司!")
}
override fun work() {
Log.e("=====","开个产品会!")
}
override fun leaveCompany() {
Log.e("=====","9点开车回家!")
}
}
- 女员工
class WomenWorker(var string :String) : AbstractDisplay(){
override fun prepare() {
Log.e("=====","补个美美的装!")
}
override fun comingCompany() {
Log.e("=====","10点 地铁上班!")
}
override fun work() {
Log.e("=====","联系客户!")
}
override fun leaveCompany() {
Log.e("=====","5点 下班回家!")
}
}
现在我们分别创建这两个类的对象并调用方法:
var display : AbstractDisplay = WomenWorker("String")
display.showWork()
var nameDisplay : AbstractDisplay = ManWorker("Name")
nameDisplay.showWork()
输出结果:
04-22 08:00:13.286 3163-3163/com.example.wuliangliang.designmodel E/=====: BBB8点 开车到公司!
04-22 08:00:13.286 3163-3163/com.example.wuliangliang.designmodel E/=====: BBB泡个咖啡!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: 打来了电脑!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: BBB开个产品会!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: 关闭了电脑!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: BBB9点开车回家!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: AAA10点 地铁上班!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: AAA补个美美的装!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: 打来了电脑!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: AAA联系客户!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: 关闭了电脑!
04-22 08:00:13.287 3163-3163/com.example.wuliangliang.designmodel E/=====: AAA5点 下班回家!
上述过程就是模版模式的简单使用中,WomenWorker和ManWorker 类中,不用关系任何执行逻辑,只需在每个方法中完成自己做的事情,运行之后就会按照真正的执行逻辑输出相应的内容。
四、登场角色
- AbstractClass(抽象类):实现业务逻辑的模版,并声明在模版方法中所使用的抽象方法
- ConcreteClass(具体类):具体实现AbstractClass角色中声明的抽象方法,这些方法会在AbstractClass的模版方法中调用。
五、模板模式的要点
- 逻辑通用
在父类中声明的业务逻辑和算法,所有的继承类都可以通用,无需在重复编写
- 父类与子类的协作
在Temple Method模式中,父类和子类是紧密联系的,子类实现父类的抽象方法必须要理解抽象方法的处理逻辑
- 父类与子类的一致性
在上述代码中所声明创建的都是AbstractClass 对象,用父类类型保存子类示例,这样即使没有制定具体的子类,程序在任何情况下都会正常工作,即无论父类类型的变量中保存那个子类实例程序都能正常工作,这种原则为里氏替换原则
6、心得
- 父类对子类的要求
我们在平时设计代码架构和扩及时,很多人站在子类的角度进行思考,从修改子类的方法去改变或实现功能,现在我们换个角度,从父类思考,在父类中处理一切业务事情,并要求子类处理功能,此时使用抽象方法达到
- 期待子类去实现父类的抽象方法
- 要求子类去实现父类的抽象方法
以上就是模版模式的简单介绍,这种模式在我们代码中见到的很多,相信大家都比较了解。