Head First 设计模式笔记(模版方法模式)

本文详细介绍了模板方法模式的概念、类图、应用场景及其实现方式。并通过一个具体的鸭子排序示例,展示了如何在实际编程中应用该模式。此外,还讨论了模板方法模式的变体及其在 JDK 中的应用。

1.定义:

在一个方法中定义一个算法骨架,而将一些步骤延迟到子类中。模版方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

2.类图:

 3.说明:

  1. 模版方法可以理解为一个方法里面包含了多个步骤的方法。该方法一般声明为final,防止被子类覆盖,保护了算法结构。
  2. 模版模式的“钩子方法”,允许通过钩子方法改名算法模版中的某些逻辑。
  3. 使用模版方法模式时,基类里面的方法是否都需要定义为抽象方法?这样子子类是否必须覆盖过多的方法。这点是需要根据实际情况考虑的。如果算法步骤切割的太细,会导致子类需要覆盖过多的方法(挺讨厌的),如果切割的不够细又会导致框架缺乏弹性。
  4. 好莱坞原则:别调用(找)我们,我们调用(找)你。目的在于解耦。
  5. 真实环境里学会选择周围的设计模式,同时也要识别设计模式的变体。例如jdk里面的Array类的sort排序方法就不是一个变体。
  6. 例子Arrays类的sort排序方法,InputStream类的read方法,JFrame类的paint方法

4.例子:Arras的排序方法,根据鸭子重量排序的例子

4.1Duck.java:

package com.test.design.template5;
//鸭子类。实现Comparable接口,需要覆盖一个compareTo的方法。
public class Duck implements Comparable<Object> {
    private String name;
    private int weight;
    public Duck() {
        // TODO Auto-generated constructor stub
    }
    public Duck(String name,int weight) {
        this.name = name;
        this.weight = weight;
    }
    @Override
    public String toString() {
        return name + ";" + weight;
    }
    @Override
    public int compareTo(Object o) {
        /*if(null == o) {
            throw new Exception("");
        }*/
        Duck duck = (Duck)o;
        if(this.weight < duck.weight) {
            return -1;
        } else if(this.weight == duck.weight) {
            return 0;
        } else {
            return 1;
        }
    }
}

4.2TestDuck.java

package com.test.design.template5;

import java.util.Arrays;

//测试类
public class TestDuck {
    public static void main(String[] args) {
        Duck d1 = new Duck("鸭子1",11);
        Duck d2 = new Duck("鸭子2",11);
        Duck d3 = new Duck("鸭子3",13);
        Duck d4 = new Duck("鸭子4",9);
        Duck[] ducks = new Duck[4];
        ducks[0] = d1;
        ducks[1] = d2;
        ducks[2] = d3;
        ducks[3] = d4;
        Arrays.sort(ducks);
        for (int i = 0; i < ducks.length; i++) {
            System.out.println(ducks[i].toString());
        }
    }
}

//输出结果:

鸭子4;9
鸭子1;11
鸭子2;11
鸭子3;13,排序正确。

如果我们看jdk中类Arrays类的sort(Object[] a)方法,会发现我们可以把sort(Object[] a)看作是一个模版方法,在里面调用了方法mergeSort(),在mergeSort方法里面传入了待排序的数组引用,同时在方法里面实现了排序。

待排序的数组自己覆盖了compareTo方法,所以具体根据什么排序是由待排序数组对象自己去实现的。根据compareTo的结果去判断是否调换数组元素的位置。直至所有的数组元素都根据定义好的规则排好序。

很明显,这不是“教科书式”的模版方法模式的例子。教科书式的模版方法模式,是定义一个抽象类,抽象类里面提供一个final的模版方法,在模版方法里面调用一系列的方法步骤,并且把需要子类去实现的步骤定义为抽象方法,让子类根据情况去具体实现。

jdk的作者希望Arrays提供一个静态方法,任何的对象数组都可以进行排序。于是定义了一个静态的sort方法,而被排序的对象内的每个元素自行提供比较大小的算法部分。虽然不是正宗的模版方法模式,但是却符合模版方法模式的精神。

//排序
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) { ... 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; } ... }

 5.总结 :

要了解什么情况使用这个模式。

能够在以后看框架代码的时候发现学过的模式。

能够识别该模式的变体。

转载于:https://www.cnblogs.com/codetree/p/8471266.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值