java設計模式-模板方法模式

模板方法模式概念

  模板方法模式屬於行爲型模式,它定義一個操作中的算法的骨架,而將一些步驟推遲到子類當中實現。父類抽取並實現的是公共方法,對於可變方法,父類做的只是定義了可變行爲的接口,具體實現留給子類去完成,實現對代碼的重複利用。


模板方法模式類圖

這裏寫圖片描述
這裏的templateMethod方法就是公共方法,是所有子類所擁有的公共行爲;abstractMethod方法就是可變的行爲,是每個子類獨特行爲,這種行爲只能由它們來實現。


模板方法模式實現

拿<<大話設計模式>>上的例子來說,學生是共用一套試卷,只是學生各自的答案是不同的;因此,試題題目是模板方法是不變的,而試題答案對於每個學生是可變的

/**
 *@author xialonglei
 *@date 2016/8/31 
 */
public abstract class AbstractTemplate {
    private String name;
    public AbstractTemplate(String name){
        this.name = name;
    }
    public void question(){
        System.out.print(name + ":1 + 1 = ");
        System.out.print(answer());
        System.out.println();
    }
    public abstract int answer();
}

public class StudentATemplate extends AbstractTemplate{
    @Override
    public int answer() {
        return 2;
    }
    public StudentATemplate(String name) {
        super(name);
    }
}

public class StudentBTemplate extends AbstractTemplate{
    public StudentBTemplate(String name) {
        super(name);
    }
    @Override
    public int answer() {
        return 3;
    }
}

測試代碼

@Test
public void templatePatternTest(){
    AbstractTemplate aTempate = new StudentATemplate("小紅");
    AbstractTemplate bTempate = new StudentBTemplate("小明");
    aTempate.question();
    bTempate.question();
}

輸出結果如下
這裏寫圖片描述


模板方法在spring中的運用

spring中的JdbcTemplate類就運用了模板方法,java在執行數據庫操作時的步驟無非如下幾步:
1. 加載驅動
2. 建立連接
3. 獲取Statement
4. 拼接參數(針對PreparedStatement)
5. 執行
6. 返回結果
7. 銷燬連接

在這裏只是簡單,介紹一下,因此針對PreparedStatement,最大的可變之處就是5,6這個部分,因此JdbcTemplate將1,2,3,4,7製作成模板(主要在execute*方法中),而對於5,6它通過匿名內部類的形式來實現(也就是說對於update、query等等操作,都對5,6通過匿名內部類有不同的實現,匿名內部類實現的都是*callback接口,*callback都是額外定義的接口)

@Override
public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
    Assert.notNull(sql, "SQL must not be null");
    Assert.notNull(rse, "ResultSetExtractor must not be null");
    if (logger.isDebugEnabled()) {
        logger.debug("Executing SQL query [" + sql + "]");
    }
    //匿名內部類
    class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
        @Override
        public T doInStatement(Statement stmt) throws SQLException {
            ResultSet rs = null;
            try {
                rs = stmt.executeQuery(sql);
                ResultSet rsToUse = rs;
                if (nativeJdbcExtractor != null) {
                    rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
                }
                return rse.extractData(rsToUse);
            }
            finally {
                JdbcUtils.closeResultSet(rs);
            }
        }
        @Override
        public String getSql() {
            return sql;
        }
    }
    //真正執行的方法
    return execute(new QueryStatementCallback());
}

這裏只貼出了其中一個query方法,其他的”套路”都跟它差不多,如果感興趣的話自己可以深究一下JdbcTemplate源碼


模板方法模式優缺點

優點:

  • 抽出不變行爲,對代碼的重複利用;要擴展的話,只需添加子類

缺點:

  • 按照我們的設計習慣,抽象類負責聲明最抽象、最一般的事情屬性和方法,實現類完成具體的事物屬性和方法。但是模板方法模式卻顛倒了,抽象類定義了部分抽象方法,由子類實現,子類執行結果影響了父類的結果,也就是子類對父類產生了影響,這在複雜的項目中,會帶來代碼閱讀的難度,而且也會讓新手產生不適感
  • 因爲引入了一個抽象類,如果具體實現過多的話,需要用戶或開發人員需要花更多的時間去理清類之間的關係

                                                              -_-沒有天才,只有勤奮的天才!                                  
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章