设计模式 9 —— 模板方法模式 设计模式 1 ——观察者模式 设计模式 2 —— 装饰者模式 设计模式 3 —— 迭代器和组合模式(迭代器) 设计模式 4 —— 迭代器和组合模式(组合) 设计模式

设计模式目录:html

设计模式 1 ——观察者模式java

设计模式 2 —— 装饰者模式 算法

设计模式 3 —— 迭代器和组合模式(迭代器)设计模式

设计模式 4 —— 迭代器和组合模式(组合)数组

设计模式 5 —— 工厂模式ide

设计模式 6 —— 单件模式post

设计模式 7 —— 命令模式测试

设计模式 8 —— 适配器和外观模式ui

设计模式 9 —— 模板方法模式this

设计模式 10 —— 状态模式

概述

介绍

模板方法抽象类

模板方法的UML图

模板方法模式定义

JDK中模板方法模式的使用

Java API中的模板方法

参考

 

模板模式是一种行为设计模式,它的实现思路是,建立一个桩方法,而且定义一些步骤让子类来实现。模板方法定义了一个算法的执行步骤,或者说可以提供一种默认的实现,这种实现归纳一部分子类或者所有子类的共同部分。

举一个例子帮助理解,假设提供一种造房子的算法。算法的步骤就是模拟造房子的过程:建地基、建支撑,最后添加墙和窗户 – 1. Fundation,2. Pillars,3. Walls,4. Windows。最重要的一点就是不能改变此建造过程,好比不可能在没用地基的时候就开始建造窗户。这个例子中,咱们就建立了一个模板方法 – 将使用不一样的方法完成对房子的建造。

为了确保子类不能重写(override)这个模板方法,应当使用final

模板方法抽象类

由于设计为一些方法的具体实现留待子类中,因此不得不安排基类为一个抽象类

HouseTemple.java

 1 package cn.telling.test.action;
 2 
 3 /**
 4  * 
 5  * @ClassName: HouseTemplate TODO
 6  * @author xingle
 7  * @date 2015-9-24 下午2:04:22
 8  */
 9 public abstract class HouseTemplate {
10     // template method, final so subclasses can't override
11     public final void buildHouse() {
12         buildFoundation();
13         buildPillars();
14         buildWalls();
15         buildWindows();
16         System.out.println("House is built.");
17     }
18 
19     // default implementation
20     private void buildWindows() {
21         System.out.println("Building Glass Windows");
22     }
23 
24     // methods to be implemented by subclasses
25     public abstract void buildWalls();
26 
27     public abstract void buildPillars();
28 
29     private void buildFoundation() {
30         System.out.println("Building foundation with cement,iron rods and sand");
31     }
32 
33 }

 

buildHouse()是模板方法并定义了在建造房子过程当中一系列方法的执行顺序。

WoodenHouse.java

 1 package cn.telling.test.action;
 2 
 3 /**
 4  * 
 5  * @ClassName: WoodenHouse
 6  * TODO
 7  * @author xingle
 8  * @date 2015-9-24 下午2:07:06
 9  */
10 public class WoodenHouse extends HouseTemplate{
11 
12     /**
13      * 
14      * @Description: TODO
15      * @author xingle
16      * @data 2015-9-24 下午2:07:15
17      */
18     @Override
19     public void buildWalls() {
20         System.out.println("Building Wooden Walls");
21         
22     }
23 
24     /**
25      * 
26      * @Description: TODO
27      * @author xingle
28      * @data 2015-9-24 下午2:07:15
29      */
30     @Override
31     public void buildPillars() {
32         System.out.println("Building Pillars with Wood coating");
33     }
34 
35 }

 

此处也应当对其余方法进行重写,可是为了简便,此处没用完成。

GlassHouse.java

 1 package cn.telling.test.action;
 2 
 3 /**
 4  * 
 5  * @ClassName: GlassHouse
 6  * TODO
 7  * @author xingle
 8  * @date 2015-9-24 下午2:05:28
 9  */
10 public class GlassHouse extends HouseTemplate{
11 
12     /**
13      * 
14      * @Description: TODO
15      * @author xingle
16      * @data 2015-9-24 下午2:05:39
17      */
18     @Override
19     public void buildWalls() {
20         System.out.println("Building Glass Walls");
21     }
22 
23     /**
24      * 
25      * @Description: TODO
26      * @author xingle
27      * @data 2015-9-24 下午2:05:39
28      */
29     @Override
30     public void buildPillars() {
31         System.out.println("Building Pillars with glass coating");
32         
33     }
34 
35 }

 

使用模板方法

用一个测试程序来测试此处已完成的模板方法。

HouseClient.java

 1 package cn.telling.test.action;
 2 
 3 /**
 4  * 
 5  * @ClassName: HousingClient TODO
 6  * @author xingle
 7  * @date 2015-9-24 下午2:06:33
 8  */
 9 public class HousingClient {
10     public static void main(String[] args) {
11 
12         HouseTemplate houseType = new WoodenHouse();
13 
14         // using template method
15         houseType.buildHouse();
16         System.out.println("************");
17 
18         houseType = new GlassHouse();
19 
20         houseType.buildHouse();
21     }
22 
23 }

 

注意,client正在调用基类的模板方法而且依赖于不一样步骤的实现细节,即这些正在使用的方法,他们一些来着基类另外一些来自子类。上述程序的输出:

 

模板方法的UML图

模板方法模式定义

模板方法模式定义一个操做中算法的骨架,而将这些步骤延迟到子类中,模板方法使得子类能够不改变一个算法的结构便可从新定义该算法的某些特定步骤。

这个模式是用来建立一个算法的模板。什么是模板?如你所见的,模板就是一个方法。更具体地说,这个方法将算法定义成一组步骤,其中的任何步骤均可以是抽象的,由子类负责实现,这能够确保算法的结构保持不变,同时由子类提供部分实现。

JDK中模板方法模式的使用

  • java.io.InputStream, java.io.OutputStream, java.io.Reader 以及 java.io.Writer 中全部非抽象方法。
  • java.util.AbstractList, java.util.AbstractSet 以及 java.util.AbstractMap中全部非抽象方法。

重要提示

  • 模板方法应该是由肯定的步骤组成。这些步骤的顺序是固定的。基类与子类之间某些方法或者实现能够有所不一样。模板方法应该是final的。
  • 大多时候,子类的调用的方法是来自于超类。可是在模板模式中,超类的模板方法调用的方法却来至于子类,这就是著名的Hollywood原则-“don’t call us, we’ll call you”。
  • 基类方法的默认实现被退化为钩子Hooks的概念,他们被设计在子类中被重写,若是你指望一些方法在子类中不被重写,你可让他们为final。好比在例子中buildFoundation()方法是final的,由于不但愿它在子类中被重写。

Java API中的模板方法

用模板方法排序

java数组类的设计者提供给咱们一个方便的模板方法用来排序。

public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a);
    }

    /** To be removed in a future release. */
    private static void legacyMergeSort(Object[] a) {
        Object[] aux = a.clone();
        mergeSort(aux, a, 0, a.length, 0);
    }

 

其中 mergeSort() 方法包含排序算法,此算法依赖于compareTo() 方法的实现来完成算法。咱们须要实现compareTo()方法,“填补”模板方法的缺憾。

/**
     * Src is the source array that starts at index 0
     * Dest is the (possibly larger) array destination with a possible offset
     * low is the index in dest to start sorting
     * high is the end index in dest to end sorting
     * off is the offset to generate corresponding low, high in src
     * To be removed in a future release.
     */
    private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low,
                                  int high,
                                  int off) {
        int length = high - low;

        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
                         ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

 

数组的排序模板方法已经提升了算法,可是你必须让这个模板方法知道如何比较鸭子。你所要作的事情就是,实现一个compareTo() 方法。

可是数组没法继承,该如何使用sort()?

sort() 的设计者但愿这个方法能使用于全部的数组,因此他们把sort() 变成事静态的方法,这样一来,任何数组均可以使用这个方法。它使用起来和它被定义在超类中是同样的。实际上,sort()并非真正定义在超类中,因此sort() 方法须要知道你已经实现了compareTo()方法,不然就没法进行排序。

要达到这一点,设计者利用了Comparable接口。你必须实现这个接口,提供这个接口所声明的方法,也就是compareTo()。

 

鸭子的实现:

 1 package cn.telling.test.action;
 2 
 3 /**
 4  * 
 5  * @ClassName: Duck
 6  * TODO
 7  * @author xingle
 8  * @date 2015-9-24 下午3:32:47
 9  */
10 public class Duck implements Comparable<Object>{
11     //咱们须要让鸭子类实现Comparable 接口,由于咱们没法真的让鸭子数组去继承数组
12     private String name ;
13     private int weight;
14     
15     public Duck(String name,int weight){
16         this.name = name;
17         this.weight = weight;
18     }
19     
20     public String toString(){
21         return name+" weight"+weight;
22     }
23 
24     /**
25      * 排序所要的方法
26      * @Description: TODO
27      * @param o
28      * @return
29      * @author xingle
30      * @data 2015-9-24 下午3:42:43
31      */
32     @Override
33     public int compareTo(Object o) {
34         //compareTo() 须要传入一只鸭子,和自己这种鸭子作比较
35         Duck otherDuck = (Duck) o;
36         if(this.weight<otherDuck.weight){
37             return -1;
38         } else if(this.weight == otherDuck.weight){
39             return 0;            
40         } else {
41             return 1;
42         }
43     }
44 }

 

测试排序鸭子的程序:

 1 package cn.telling.test.action;
 2 
 3 import java.util.Arrays;
 4 
 5 /**
 6  * 
 7  * @ClassName: DuckSortTestDrive
 8  * TODO
 9  * @author xingle
10  * @date 2015-9-24 下午3:35:44
11  */
12 public class DuckSortTestDrive {
13     
14     public static void main(String[] args) {
15         Duck[] ducks = { new Duck("D1", 8), new Duck("D2", 6),
16                 new Duck("D3", 2),new Duck("D4", 5) };
17         System.out.println("Bofore sorting  ");
18         dispaly(ducks);
19         //调用Array类的静态方法sort(),让后将鸭子数组当作参数传入
20         Arrays.sort(ducks);
21         System.out.println("After sorting  ");
22         dispaly(ducks);
23     }
24 
25     /**
26      * TODO
27      * @param ducks
28      * @author xingle
29      * @data 2015-9-24 下午3:39:17
30      */
31     public static void dispaly(Duck[] ducks) {
32         for(int i = 0;i<ducks.length;i++){
33             System.out.println(ducks[i]);
34         }
35         
36     }
37 
38 }

 

执行结果:

 


参考:

  1. Java中的模板模式
  2. [Head First设计模式]云南米线馆中的设计模式——模版方法模式
  3. 《First Head 设计模式》 第8章 封装算法:模板方法模式
相关文章
相关标签/搜索