模板方法(Template Method)
Intent
定义算法框架,并将一些步骤的实现延迟到子类。
通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构。
Class Diagram

Implementation
冲咖啡和冲茶都有类似的流程,但是某些步骤会有点不一样,要求复用那些相同步骤的代码。

public abstract class CaffeineBeverage {final void prepareRecipe() {boilWater();brew();pourInCup();addCondiments();}abstract void brew();abstract void addCondiments();void boilWater() {System.out.println("boilWater");}void pourInCup() {System.out.println("pourInCup");}}
public class Coffee extends CaffeineBeverage {@Overridevoid brew() {System.out.println("Coffee.brew");}@Overridevoid addCondiments() {System.out.println("Coffee.addCondiments");}}
public class Tea extends CaffeineBeverage {@Overridevoid brew() {System.out.println("Tea.brew");}@Overridevoid addCondiments() {System.out.println("Tea.addCondiments");}}
public class Client {public static void main(String[] args) {CaffeineBeverage caffeineBeverage = new Coffee();caffeineBeverage.prepareRecipe();System.out.println("-----------");caffeineBeverage = new Tea();caffeineBeverage.prepareRecipe();}}
boilWaterCoffee.brewpourInCupCoffee.addCondiments-----------boilWaterTea.brewpourInCupTea.addCondiments
JDK
- java.util.Collections#sort()
@SuppressWarnings({"unchecked", "rawtypes"})default void sort(Comparator<? super E> c) {Object[] a = this.toArray();Arrays.sort(a, (Comparator) c);ListIterator<E> i = this.listIterator(); // listIterator是延迟到子类实现的for (Object e : a) {i.next();i.set((E) e);}}
- java.util.AbstractList#indexOf()
public int indexOf(Object o) {ListIterator<E> it = listIterator(); // 同上if (o==null) {while (it.hasNext())if (it.next()==null)return it.previousIndex();} else {while (it.hasNext())if (o.equals(it.next()))return it.previousIndex();}return -1;}
java.lang.ClassLoader
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name); // 来检查是否已经加载类if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {c = parent.loadClass(name, false); // 让父加载器尝试加载加载} else {c = findBootstrapClassOrNull(name); // 让 bootstrap class loader尝试加载}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name); // 模板设计模式,如果都没有找到的话,则从findCLass中去找,这个findClass ,子类去复写这个方法// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}
ClassLoader实用了 模板设计模式
1、首先看是否有已经加载好的类。
2、如果父类加载器不为空,则首先从父类类加载器加载。
3、如果父类加载器为空,则尝试从启动加载器加载。
4、如果两者都失败,才尝试从findClass方法加载。 // 子类来实现
- java.io.InputStream#skip() // 都是在子类中才实现
- java.io.InputStream#read()
