设计模式(四)--模板方法模式

  这是一个在许多优秀的开源项目中LZ见的最多的一个设计模式,也是LZ觉得最为优秀的一个设计模式。

  模板方法模式,一般是为了统一子类的算法实现步骤,所使用的一种手段或者说是方式。它在父类中定义一系列算法的步骤,而将具体的实现都推迟到子类。

  下面LZ给举一个例子,比如我们有一个接口,里面就一个方法,是用来制造一个HTML页面,如下。

public interface PageBuilder{
    String buildHtml();
}

  这个接口很简单,就是直接制造一个html页面内容,假设不使用模板方法模式,直接让各个子类去直接实现这个接口,那么肯定实现的方式多种多样,而且步骤也乱七八糟,这样不利于维护和扩展。所以我们可以使用模板方法模式,将这个过程给制定好,然后把具体的内容填充交给子类就好,这样这些子类生成的HTML页面就会一致。

  基于这个目的,我们定义如下抽象类,去实现这个接口,并且我们定义好步骤。

public abstract class AbstractPageBuilder implements PageBuilder{

    private static final String DEFAULT_DOCTYPE = "<!DOCTYPE HTML>";

    private StringBuffer stringBuffer = new StringBuffer();

    public String bulidHtml() {
        stringBuffer.append(DEFAULT_DOCTYPE);
        stringBuffer.append("<html>");
        stringBuffer.append("<head>");
        appendTitle(stringBuffer);
        appendMeta(stringBuffer);
        appendLink(stringBuffer);
        appendScript(stringBuffer);
        stringBuffer.append("</head>");
        appendBody(stringBuffer);
        stringBuffer.append("</html>");
        return stringBuffer.toString();
    }
    //供子类选择性覆盖
    protected void appendMeta(StringBuffer stringBuffer){
    }
    //供子类选择性覆盖
    protected void appendLink(StringBuffer stringBuffer){
    }
    //供子类选择性覆盖
    protected void appendScript(StringBuffer stringBuffer){
    }
   //模板方法 添加标题
    protected abstract void appendTitle(StringBuffer stringBuffer);
   //模板方法 添加body
    protected abstract void appendBody(StringBuffer stringBuffer);

}

  子类只要实现两个模板方法,就可以成功创建html页面。

public class MyPageBuilder extends AbstractPageBuilder{
    
    protected void appendMeta(StringBuffer stringBuffer) {
        stringBuffer.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />");
    }

    protected void appendTitle(StringBuffer stringBuffer) {
        stringBuffer.append("<title>你好</title>");
    }

    protected void appendBody(StringBuffer stringBuffer) {
        stringBuffer.append("<body>你好,世界!</body>");
    }

    public static void main(String[] args) {
        PageBuilder pageBuilder = new MyPageBuilder();
        System.out.println(pageBuilder.bulidHtml());
    }
    
}

  meta,link和script是留给子类覆盖的,当然子类可以选择不覆盖,那么生成的HTML就没有meta,link和script这三种标签,如果想有的话,就可以覆盖其中任意一个。

  为了不强制子类实现不必要的抽象方法,但又不剥夺子类自由选择的权利,我们在父类提供一个默认的空实现,来让子类自由选择是否要覆盖掉这些方法。

 

posted @ 2018-11-29 11:39  肖冬  阅读(172)  评论(0编辑  收藏  举报