转:http://tianli.blog.51cto.com/190322/45564
转:http://www.cnblogs.com/flxLove/archive/2009/08/17/1548373.html
摘要:本文深入浅出的讲述了设计模式中的
模板
模式
,
并给出了简单的示例
,
例子浅显易懂
,
并附带源代码。
模板模式属于行为型模式,其意图是定义一个操作的算法骨架,而将一些步骤延迟到子类中,可以不改变一个算法的结构即可以重新定义概算法的某些特定步骤。
考虑一些提供了一个冒泡排序算法的类,其定义了冒泡算法的基本骨架:在这个算法中定义了两个抽象的操作swap(int)即交换两个元素的位置和outOforder(index)即当前的元素是否符合顺序。执行分类的方法,Dosort()调用了抽象的方法,执行既定的动作。在实现int类型的冒泡排序中,只要实现两个抽象的方法就可以通过调用Dosort来获取正确的结果。
适用性:
l
一次性实现一个算法的不变部分,并将可变的部分留给子类来实现,
l
各个子类中公共的行为应该被提取出来并集中到一个公共父类中以避免代码的重复。
l
控制子类的扩展,模板方法旨在特定点调用”hook”操作
参与者:
AbstractClass(抽象类)
定义抽象的原语操作,具体子类将重订一他们以实现一个算法的各个步骤,
实现一个木板方法,定义一个算法的骨架,该模板方法不仅调用原语操作,也调用定义在AbstractClass或其他对象中的操作。
实现原语操作以完成算法中与特定子类相关的步骤。
ConcreteClass(具体类)
实现原语操作以完成算法中与特定子类相关的步骤。
相互关系
:
具体类靠抽象类中的模板方法来完成算法中不变的部分。
模板方法导致一种反向的控制结构,即父类调用子类的方法。模板方法调用下列类型的操作:
具体的操作,具体的
AbstractClass
的操作,原语操作,钩子操作等。
以上的代码示例:
BubbleSorter
抽象类
package
template;
public
abstract
class
BubbleSorter{
private
int
operations
;
protected
int
length
= 0;
protected
int
doSort(){//
掉用抽象方法
operations
= 0;
if
(
length
<=1)
return
operations
;
for
(
int
nextToLast =
length
-2;nextToLast>=0;nextToLast--)
for
(
int
index = 0;index<=nextToLast;index++){
if
(outOfOrder(index)){
swap(index);
operations
++;
}
}
return
operations
;
}
protected
abstract
void
swap(
int
index);//
定义的抽象方法
protected
abstract
boolean
outOfOrder(
int
index);
}
具体子类:
package
template;
public
class
IntBubbleSorter
extends
BubbleSorter{
private
int
[]
array
;
public
int
sort(
int
[] array){
this
.
array
= array;
length
= array.
length
;
return
doSort();
}
protected
void
swap(
int
index){
int
temp =
array
[index];
array
[index]=
array
[index+1];
array
[index+1]=temp;
}
protected
boolean
outOfOrder(
int
index){
return
array
[index]>
array
[index+1];
}
}
客户端的调用:
package
template;
public
class
Client{
public
static
void
main(String[] args){
int
[] intArray = {20,14,16,9,10,13,18};
double
[] dbArray = {20.50,20.43,20.88,20.45,20.72};
IntBubbleSorter ibs =
new
IntBubbleSorter();
ibs.sort(intArray);
System.
out
.println(
"Int sorter"
);
for
(
int
i =0;i<intArray.
length
;i++)
System.
out
.print(intArray[i]+
","
);
System.
out
.println();
DoubleBubbleSorter dbs =
new
DoubleBubbleSorter();
dbs.sort(dbArray);
System.
out
.println(
"Double sorter"
);
for
(
int
i =0;i<dbArray.
length
;i++)
System.
out
.print(dbArray[i]+
","
);
System.
out
.println();
}
}
总结:模板方法在面向对象的设计中使用的比较多,概念理解也比较简单,在实际的应用中如果加以小心的求证,便可以灵活的掌握。
/////////////////////////////////////////////////////////
由一个简单的servlet引发的思考——设计模式的模板模式
一个普通的servlert类,我们去继承的HttpServlet类中有五个方法,init(),service(),doGet(),doPost(),destry()方法,我们自己写的servlet中要实现或者重写里面的方法,但是里面的service方法是不能重写的。当我们的参数请求到servlet类中,会到父类中的service方法中判断method是Post还是Get方式,
public final void service(){
if(method.equals("get")){doGet()}
else {doPost()}
}
public abstract void doGet(){}
Public abstract void doPost(){}
所以要求在HttpServlet类中有doPost和doGet方法,但是这两个方法的执行逻辑是不确定的,这时可以在HttpServlet里面定义doGet和doPost抽象类,供子类继承实现,或者定义其方法,让子类去重写。service()方法被称为模板法,去调用子类的实现方法doGet和doPost方法。
Httpservlet ser=new ActionServlet();
ser.service();
这种父类调用子类的实现的就被设计模式的模板模式
模板模式是一种最简单的设计模式,他的定义思想是,在一个操作的算法中搭一个骨架,把一些步骤延迟到子类中实现执行。
由此可以扩展的几个知识点,抽象类的作用,以及抽象类的设计与接口设计时选择接口还抽象类的问题。
由模板模式的可以很明显看出抽象类的作用和接口设计的区别,接口中的方法是全部不实现的,抽象类中可以不是抽象的方法。
适用情况:
1) 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
2) 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。其实这可以说是一种好的编码习惯了。
3) 控制子类扩展。模板方法只在特定点调用操作,这样就只允许在这些点进行扩展。比如上面runBare()方法就只在runTest前面适用setUp方法。如果你不愿子类来修改你的模板方法定义的框架,你可以采用两种方式来做:一是在API中不体现出你的模板方法;二、将你的模板方法置为final就可以了。
可以看出,使用模板方法模式可以将代码的公共行为提取出来,达到复用的目的。而且,在模板方法模式中,是由父类的模板方法来控制子类中的具体实现。这样你在实现子类的时候,根本不需要对业务流程有太多的了解。