说说优秀设计模式--模板方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了说说优秀设计模式--模板方法相关的知识,希望对你有一定的参考价值。
说说优秀设计模式--模板方法2016-1-1 by Damon
说说模板方法(Template Method)
一句话总结
父类方法调用抽象方法,方法抽象定义在父类,实际实现处理交给子类,按照流程完成整件事就是“模板方法模式”。
有什么好处
遵照父类定义的前提下,不同的子类可以给父类抽象的模板方法提供不同的实现,提供拓展能力。
简单的小例子
父类: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); }
以上是关于说说优秀设计模式--模板方法的主要内容,如果未能解决你的问题,请参考以下文章