先从模板方法模式开始说起吧,这个模式以前看的时候没有太注意,现在又看了一遍,发现这个模式了不得呀(路人甲:其实每个模式都了不得,嘿嘿)。就是想武侠剧中的飞叶伤人,普通人眼里树叶就是树叶,而在高手眼里,那就是“草木皆兵”。同样是简单的一个继承,人家GoF就能给你整成一个模式,还是个了不得的模式。难道这就是所谓的境界吗?
为什么会有这种感慨呢?且看我慢慢道来。
[定义]
先来看一下模板方法的定义,不然你可能不好理解我说的一些比喻。
GoF:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
官方实现代码如下:
抽象父类代码:
/**
* 抽象父类,定义算法骨架和基本方法
* @author the5fire
*
*/
abstract class AbstractClass {
/**
* 模板方法的声明和实现,算法骨架
*/
public void TemplateMethod() {
System.out.println("就应该这么计算:");
PrimitiveOperation2();
PrimitiveOperation1();
}
/**
* 基本方法的声明(由子类实现)
*/
protected abstract void PrimitiveOperation1();
/**
* 基本方法的声明(由子类实现)
*/
protected abstract void PrimitiveOperation2();
}
具体子类A代码:
/**
* 子类A,实现抽闲父类的基本方法
* @author the5fire
*
*/
public class ConcreteClassA extends AbstractClass {
/**
* 基本方法实现
*/
@Override
public void PrimitiveOperation1() {
System.out.println("子类A实现1方法");
}
/**
* 基本方法实现
*/
@Override
public void PrimitiveOperation2() {
System.out.println("子类A实现2方法");
}
}
具体子类B代码:
/**
* 子类B实现抽象父类中的基本方法
* @author the5fire
*
*/
public class ConcreteClassB extends AbstractClass {
/**
* 基本方法实现
*/
@Override
public void PrimitiveOperation1() {
System.out.println("子类B实现1方法");
}
/**
* 基本方法实现
*/
@Override
public void PrimitiveOperation2() {
System.out.println("子类B实现2方法");
}
}
客户端代码:
public class Client {
public static void main(String[] args) {
AbstractClass abstractClass;
/**
* 这里可以使用多态或者是工厂实现不同子类的调用
*/
abstractClass = new ConcreteClassA();
abstractClass.TemplateMethod();
abstractClass = new ConcreteClassB();
abstractClass.TemplateMethod();
}
}
[个人评论]
咂看之下,这个代码不过是使用了子类在继承父类之后覆盖了父类中的方法罢了。然而我个人认为这个模式的精华之处就在于TemplateMethod这个方法。这个方法使得你在使用继承时有所限制,这样可以一定程度上防止继承被滥用。
正是这么一个限制也使得这个抽象的父类已经不再是一个类了,而是一个平台。一个平台的概念就是我给你提供工具,给你提供方法,但是你要按照我说的去做。
从现实生活中来说,这个叫做抽象类的家伙摇身一变从一个打工仔变成了一个领导者,这不仅仅是工资的转变,更是思想和视角的转变。
[扩展应用]
这个模板方法可谓是无处不在,它不仅仅用在软件设计上,或者是具体算法的设计上,也可以用在网站或者项目的整体架构上。咱们不能只盯着代码看。
Wordpress
比如说我的这个网站,用的着名的wordpress构架而成的。刨除网站展示平台来讲,Wordpress本身就是一个平台,具体就体现在它强大的插件能力。任何一个开发者都可以开发自己的插件或者自己的主题样式,然后发布出去让别人使用。而任何人可以开发自己的插件和主题这本身就是继承并实现了wordpress里面的某一个抽象父类。
但是这些插件为什么放到wordpress里面就能直接使用呢,开发者只管实现就行了呢。其实这里面用到的就是模板方法。
具体的流程开发者不必考虑,只需要考虑实现的效果。插件在使用的时候先加载哪一个或者是以什么样的方式来加载这个插件都是在平台里面定义好的。开发者不用干涉,也无权干涉。
操作系统
其实不光是网站架构,就那操作系统来说也是如此,微软的之所以有如此大的用户粘度,主要还是归功于系统可支持的丰富多彩的软件。这也是微软之所以在起初能比苹果更快的打入到千家万户的原因之一。
软件商要开发windows系统的软件,那么你就要接受微软制定的标准,比如说PE格式。接受标准之后你才能在windows上面运行。这里面微软的提供标准就是一个抽象类,而里面也会有一个模板方法来定义算法骨架。
JDK
在java语言中也有模板方法的使用,就是HttpServlet。有兴趣的可以自己看一下。不得不说java中让我比较喜欢的就是能够看一些外围的代码。
[原则]
其实这个模式里面体现了一个很好的设计原则,那就是控制反转,也叫做依赖注入。指的就是程序的实现并不依赖于具体的实现,而是依赖于抽象。这么做的好处就是不会使得程序实现过于死板(如果只是依赖某一具体实现,他的灵活性你可以想象的到),让程序具有较高的灵活性。其实这个就像是处世之道,不能太实在,要懂得变通。
- from the5fire.com
----EOF-----
微信公众号:Python程序员杂谈
微信公众号:Python程序员杂谈