a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 116|回复: 0

[基础知识] Java设计模式:模板方法模式

[复制链接]
发表于 2012-8-4 12:37:27 | 显示全部楼层 |阅读模式
一、引子 - ?9 |5 L" P! j: |: z( b( V/ h" T
  这是一个很简单的模式,却被很是普遍的使用。之所以简单是因为在这个模式中仅仅使用到了担任关系。
1 |( _# [; n. l3 F4 T! r9 u  担任关系因为自身的缺陷,被专家们扣上了“罪恶”的帽子。“使用委派关系庖代担任关系”,“尽量使用接口实现而不是抽象类担任”等等专家警告,让我们这些菜鸟对担任“另眼相看”。' f0 R# y+ r, M. Z, v
  其实,担任仍是有良多自身的利益地址。只是被巨匠滥用的似乎错误谬误加倍较着了。合理的操作担任关系,仍是能对你的系统设计起到很好的浸染的。而模板体例模式就是其中的一个使用典型。
: w6 V. x, }/ s3 r# X9 Z  二、界说与结构
" B6 B7 b. ^$ G+ C, n+ b  GOF给模板体例(Template Method)模式界说一个操作中的算法的骨架,而将一些轨范延迟到子类中。使得子类可以不改变一个算法的结构即可重界说该算法的某些特定轨范。这里的算法的结构,可以理解为你按照需求设计出来的营业流程。特定的轨范就是指那些可能在内容上存在变数的环节。4 N" G; F/ H) G' I. K) _0 `
  可以看出来,模板体例模式也是为了巧妙解决转变对系统带来的影响而设计的。使用模板体例使系统扩展性增强,最小化了转变对系统的影响。这一点,不才面的举例中可以很较着的看出来。
" z& |4 \- k7 r* ]6 W  来看下这个简单模式的结构吧:
9 g& N/ o9 z8 H1 R- L3 }+ r  1) AbstractClass(抽象类):界说了一到多个的抽象体例,以供具体的子类来实现它们;而且还要实现一个模板体例,来界说一个算法的骨架。该模板体例不仅挪用前面的抽象体例,也可根柢用其他的操作,只要能完成自身的使命。
, `4 w- x: X2 o# o0 I. X  2) ConcreteClass(具体类):实现父类中的抽象体例以完成算法中与特定子类相关的轨范。
9 v0 }" d# E* A/ o& f  下面是模板体例模式的结构图。直接把《设计模式》上的图拿过滥暌姑下: ' e+ |% C9 Y& M9 R- V* I
7 s2 A) b6 |% r/ o

0 ^" c& ~9 v3 e1 F1 o  三、举例
1 J8 Z; R. g' \  b; G. W  仍是在我刚刚剖析完源码的JUnit中找个例子吧。JUnit中的TestCase以及它的子类就是一个模板体例模式的例子。在TestCase这个抽象类中将整个测试的流程设置好了,好比先执行Setup体例初始化测试前提,在运行测试体例,然后再TearDown来打消测试设置。可是你将在 Setup、TearDown琅缦沔作些什么呢?鬼才知道呢!!是以,而这些轨范的具体实现都延迟到子类中去,也就是你实现的测试类中。) z* K' i& A; s& ^
  来看下相关的源代码吧。) K+ O1 q- \5 c, h+ O, ^
  这是TestCase中,执行测试的模板体例。你可以看到,琅缦沔正像前面界说中所说的那样,它拟定了“算法”的框架——先执行setUp体例来做下初始化,然后执行测试体例,最后执行tearDown释放你获得的资本。# {- }+ _& F0 b
public void runBare() throws Throwable {
9 g# I# q* P- x setUp();, ~% O$ E. P; U6 x; d. \
 try {
; Y, E3 U- c2 @1 u  runTest();
) x, `: L4 Z) Q) e0 R }
# P4 h2 x9 E' F, R/ e! l5 s finally {
; n3 K3 `! D7 X, Y  tearDown();; n9 i- J( x$ K# H) S0 P* w
 }
% R0 W! Y7 D0 o7 U) t% _5 B  A6 X' D}5 U& t  \4 a* w- O4 }
; U/ t5 K4 b- n' ?9 V& h
  这就是膳缦沔使用的两个体例。与界说平分歧的是,这两个体例并没有被实现为抽象体例,而是两个空的无为体例(被称为钩子体例)。这是因为在测试中,我们并不是必需要让测试轨范使用这两个体例来初始化和释放资本的。如不美观是抽象体例,则子类们必需给它一个实现,不管用到用不到。这显然是不合理的。使用钩子体例,则你在需要的时辰,可以在子类中重写这些体例。
6 B/ H) `% D/ T2 I0 T( `/ x6 K4 @! l8 r# s7 V4 \
protected void setUp() throws Exception {}
; X( N  Q1 ~3 wprotected void tearDown() throws Exception {}9 b8 N  j5 D7 Y) R2 ]" {2 D
7 F! [& D2 I0 P; ?( V. T6 R
  四、合用情形
% r0 |0 _0 u' J9 p  B" f
) k/ C6 q% ^( D7 v  按照膳缦沔临界说的剖析,以及例子的声名,可以看出模板体例合用于以下情形:* F, D* m1 o1 T! ]; Y. M1 x
  1) 一次性实现一个算法的不变的部门,并将可变的行为留给子类来实现。1 D; e5 L2 A& u0 ]2 j. h
  2) 各子类中公共的行为应被提掏出来并集中到一个公共父类中以避免代码一再。其拭魅这可以说是一种好的编码习惯了。7 O/ n7 @! Q' b5 }9 l9 ]
  3) 节制子类扩展。模板体例只在特定点挪用操作,这样就只许可在这些点进行扩展。好比膳缦沔runBare()体例就只在runTest前面合用setUp体例。如不美观你不愿子类来改削你的模板体例界说的框架,你可以采用两种体例来做:一是在API中不浮现出你的模板体例;二、将你的模板体例置为final就可以了。
/ D, [; f+ y' {' w- M8 w  ]" M* }7 f$ c  可以看出,使用模板体例模式可以将代码的公共行为提掏出来,达到改暌姑的目的。而且,在模板体例模式中,是由父类的模板体例来节制子类中的具体实现。这样你在实现子类的时辰,根柢不需要对营业流程有太多的体味。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-4-29 19:24 , Processed in 0.260599 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表