2016-1-1 by Damon
父类方法调用抽象方法,方法抽象定义在父类,实际实现处理交给子类,按照流程完成整件事就是“模板方法模式”。
遵照父类定义的前提下,不同的子类可以给父类抽象的模板方法提供不同的实现,提供拓展能力。
父类:AbstractDisplay
public abstract class AbstractDisplay {
// 方法抽象定义在父类
public abstract void open();
public abstract void print();
public abstract void close();
// 父类方法调用抽象方法
public final void diplay() {
open();
for(int i = 0; i < 5; i++){
print();
}
close();
}
}子类:CharDisplay
public class CharDisplay extends AbstractDisplay {
private char ch;
public CharDisplay(char ch) {
this.ch = ch;
}
public void open() {
// 具体实现
System.out.print("<<");
}
public void print() {
// 具体实现
System.out.print(ch);
}
public void close() {
// 具体实现
System.out.println(">>");
}
}子类:StringDisplay
public class StringDisplay extends AbstractDisplay {
private String string;
private int width;
public StringDisplay(String string){
this.string = string;
this.width = string.getBytes().length;
}
public void open() {
// 具体实现
printLine();
}
public void print() {
// 具体实现
System.out.println("|" + string + "|");
}
public void close() {
// 具体实现
printLine();
}
private void printLine(){
System.out.print("+");
for(int i = 0; i < width; i++){
System.out.print("-");
}
System.out.println("+");
}
}测试:Main
public class Main {
/**
* <p>main</p>
* <p></p>
* @author damon
* @date 2016年1月4日
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
AbstractDisplay d1 = new CharDisplay(‘H‘);
d1.diplay();
// AbstractDisplay d2 = new StringDisplay("Hello");
// d2.diplay();
}
}前段时间在研究SpringMVC的前端控制器DispatchServlet时看到初始化过程里面有很多类似“模板方法”的变相体现,下面举例分享一下:
HttpServletBean 类
// 模板方法模式的变相体现
public final void init() throws ServletException {
// 忽略其他内容
// 模板方法调用
initServletBean();
}
/**
* Subclasses may override this to perform custom initialization.
* All bean properties of this servlet will have been set before this
* method is invoked.
* <p>This default implementation is empty.
* @throws ServletException if subclass initialization fails
* 大体翻译:空实现,不处理事情,子类将会提供初始化的实现
* 分析:相比模板方法模式,模板方法模式在父类的模板方法被定义为抽象的,子类必须提供实现,
* 这里采用父类模板方法空实现,子承父类protected的限制,好处是子类可以有选择的实现
*/
protected void initServletBean() throws ServletException {
}HttpServletBean 类 子类 FrameworkServlet 类
// 模板方法子类实现
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring FrameworkServlet ‘" + getServletName() + "‘");
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet ‘" + getServletName() + "‘: initialization started");
}
long startTime = System.currentTimeMillis();
try {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
catch (ServletException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
catch (RuntimeException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
if (this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
this.logger.info("FrameworkServlet ‘" + getServletName() + "‘: initialization completed in " +
elapsedTime + " ms");
}
}同样的设计还有,如
FrameworkServlet 类
protected WebApplicationContext initWebApplicationContext() {
// 忽略其他内容
if (!this.refreshEventReceived) {
// 模板方法调用
onRefresh(wac);
}
}
/**
* Template method which can be overridden to add servlet-specific refresh work.
* Called after successful context refresh.
* <p>This implementation is empty.
* @param context the current WebApplicationContext
* @see #refresh()
*/
protected void onRefresh(ApplicationContext context) {
// For subclasses: do nothing by default.
}FrameworkServlet 类 子类 DispatcherServlet 类
// 模板方法子类实现
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}原文:http://damon188.blog.51cto.com/8846760/1746619