简介
模板方法设计模式是一种非常依赖继承和抽象类的设计模式,在父类模板方法中封装子类的算法框架以及方法的执行顺序。子类放弃对自己的控制权,改为父类通知子类调用。
面向对象语言的模板方法设计模式(Java)
传统面向对象基于抽象类和继承实现
abstract public class AbParent{
// 模板方法
final void init(){
fn1();
fn2();
}
abstract void fn1();
abstract void fn2();
}
public class SpeChild1 extends AbParent{
public void fn1(){
System.out.println("这是具体类1的方法1");
}
public void fn2(){
System.out.println("这是具体类1的方法2");
}
}
public class SpeChild2 extends AbParent{
public void fn1(){
System.out.println("这是具体类2的方法1");
}
public void fn2(){
System.out.println("这是具体类2的方法2");
}
}
public class test{
public static void main(String[] args){
AbParent s1 = new SpeChild1();
s1.init();
AbParent s2 = new SpeChild2();
s2.init();
}
}
抽象类中init方法就是模板方法,父类规定了子类的实现方法以及执行顺序
JavaScript中的模板方法模式
JavaScript没有类和继承的概念,更别说抽象类的概念,并且不存在类型检查,造成在JavaScript中很难规定子类必须去实现某个方法,只能人为的进行约束
function AbParent(){}
AbParent.prototype.init = function(){
this.fn1();
this.fn2();
}
AbParent.prototype.fn1 = function(){}
AbParent.prototype.fn2 = function(){}
function SpeChild1 (){}
SpeChild1.prototype = new AbParent();
SpeChild1.prototype.fn1 = function(){
console.log("这是具体类1的方法1");
}
SpeChild1.prototype.fn2 = function(){
console.log("这是具体类1的方法2");
}
function SpeChild2 (){}
SpeChild2.prototype = new AbParent();
SpeChild2.prototype.fn1 = function(){
console.log("这是具体类2的方法1");
}
SpeChild2.prototype.fn2 = function(){
console.log("这是具体类2的方法2");
}
new SpeChild1().init();
new SpeChild2().init();
上述代理说实话意义不大,如果没有进行方法的覆盖,不会知道错误。这个时候可以抛出错误进行提示
AbParent.prototype.fn1 = function(){
throw new Error("子类必须重写方法fn1");
}
AbParent.prototype.fn2 = function(){
throw new Error("子类必须重写方法fn2");
}
也可以使用Typescsript达到类型检查和提示的目的
abstract class AbParent{
fn1():()=>void;
fn2():()=>void;
final init = fucntion ():void{
fn1();
fn2();
}
}
class SpeChild1 extends AbParent{
fn1(){
console.log("这是具体类1的方法1");
}
fn2(){
console.log("这是具体类1的方法2");
}
}
class SpeChild2 extends AbParent{
fn1(){
console.log("这是具体类2的方法1");
}
fn2(){
console.log("这是具体类2的方法2");
}
}
SpeChild1:AbParent = new SpeChild1();
SpeChild2:AbParent = new SpeChild2();
SpeChild1.init();
SpeChild2.init();
得益于JavaScript的特性在本例中的继承关系好像表现的不是这么的重要,可以使用如下方法实现模板方法模式
function Parent(param){
const fn1 = param.fn1 || function(){
throw new Error("必须传递方法fn1");
}
const fn2 = param.fn2 || function(){
throw new Error("必须传递方法fn2");
}
function F(){};
F.prototype.init = function(){
fn1();
fn2();
}
return F
}
总结
模板方法设计模式子类的方法和执行顺序不变,所以可以把这部分抽象到父类中模板方法中。而子类进行方法的具体实现。