设计模式之模板方法模式(三)

模板方法模式是一个很常见的模式,可是也须要咱们拥有一双锐利的眼睛,由于模板方法有许多实现,而他们看起来并不必定和书上所讲的设计一致。java

这个模式很常见是由于对建立框架来讲,这个模式简直棒极了。由框架控制如何作事情,而由你(使用这个框架的人)指定框架算法中每一个步骤的细节。算法

用模板方法排序

咱们常常须要数组作什么事情?对了!排序。编程

Java数组类的设计者提供给咱们一个方便的模板方法用来排序。让咱们看看这个方法如何运行:设计模式

这里有两个方法,共同提供排序的功能,这里提供了Java的部分源码数组

public static void sort(Object[] a) {
    Object aux[] = (Object[])a.clone();
    mergeSort(aux, a, 0, a.length, 0);
}

private static void mergeSort(Object[] src, Object[] dest,int low,int high, int off) {
    // 这里省略其余实现
    int length = high - low;
    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方法须要知道你已经实现了这个compareTo方法,不然就没法进行排序。工具

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

public class Duck implements Comparable<Duck> {
    String name;
    int weight;
  
    public Duck(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }
 
    public String toString() {
        return name + " weighs " + weight;
    }
  
    public int compareTo(Duck object) {
 
        Duck otherDuck = object;
  
        if (this.weight < otherDuck.weight) {
            return -1;
        } else if (this.weight == otherDuck.weight) {
            return 0;
        } else { // this.weight > otherDuck.weight
            return 1;
        }
    }
}

让咱们来测试下这个程序测试

public class DuckSortTestDrive {

    public static void main(String[] args) {
        Duck[] ducks = { 
                        new Duck("Daffy", 8), 
                        new Duck("Dewey", 2),
                        new Duck("Howard", 7),
                        new Duck("Louie", 2),
                        new Duck("Donald", 10), 
                        new Duck("Huey", 2)
         };

        System.out.println("Before sorting:");
        display(ducks);

        Arrays.sort(ducks);
 
        System.out.println("\nAfter sorting:");
        display(ducks);
    }

    public static void display(Duck[] ducks) {
        for (Duck d : ducks) {
            System.out.println(d);
        }
    }
}

观察鸭子排序的内部工做

让咱们追踪Array类的sort模板方法的工做过程。咱们会看到模板方法是如何控制算法的,以及在算法中的某些点上它是如何要求咱们的鸭子提供某个步骤的实现的ui

  1. 首先咱们须要鸭子数组
  2. 而后调用Array类的sort模板方法,并传入鸭子数组
  3. 想要排序一个数组,你须要一次又一次地比较两个项目,直到整个数组都排序完毕
  4. 若是鸭子的次序不对,就用Array的具体swap方法将二者对调
  5. 排序方法会持续比较并对调鸭子,直到整个数组次序是正确的

是否是很惊讶,这个也是模板方法的一种实现呢。虽然不是教科书上的模板方法,但它的实现仍然符合模板方法模式的精神。在Java的API中,还能够看到其余的。好比java.io的InputStream类有一个read()方法,是由子类实现的,而这个方法又会被read(byte b[],int off,int len)模板方法使用。

还有模板方法和策略模式都是封装组合,一个用组合,一个用继承,你搞明白了吗?若是仍是太笼统的话,那么,小编请你仔细翻书《Head First设计模式》看一下这章吧,而后咱们再讨论。

设计箱内的工具

总结时间到了

  • OO基础

    抽象、封装、继承、多态

  • OO原则

    封装变化

    多用组合,少用继承

    针对接口编程,不针对实现编程

    为交互对象之间的松耦合设计而努力

    依赖抽象,不要依赖具体类

    类应该对扩展开放,对修改关闭

    只和朋友交谈

    别找我,我会找你(咱们最新的原则提醒你,由超类主控一切,当它们须要的时候,天然会去调用子类,这就跟好莱坞同样

    只和朋友交谈

  • OO模式

    『策略模式』、『观察者模式』、『装饰者模式』、『抽象工厂模式』、『工厂方法模式』、『单例模式』、『命令模式』、『适配器模式』、『外观模式』

    模板方法模式』在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类能够在不改变算法结构的状况下,从新定义算法中的某些步骤。

学习完模板方法模式,小编才知道,原来在平时频繁使用的设计模式中,他也占据着一个重要的地位,学习以前,小编是全然不知呀。此次终于get到这个模式,而且储备了知识,还须要慢慢消化噢。

下次,咱们一块儿走进迭代器和组合模式的世界。

爱生活,爱学习,爱感悟,爱挨踢

相关文章
相关标签/搜索