java设计模式之模板方法
在设计模式中模板方法其实挺好理解的,它将多个类中共同的逻辑抽象成一个模板方法,放在父类之中。
然后把实际场景中不确定的部分写成一个抽象方法,具体逻辑由子类实现,当然实际执行的时候模板方法调用的是子类中重新实现的方法。
这样就给父类中的模板方法实现了复用,而同时又给子类留下了扩展点。
模板方法的应用很多,Java Servlet、JUnit TestCase、Java InputStream、Java AbstractList的设计中都应用到了模板方法。
InputStream中read()方法就是一个模板方法,它需要调用另外一个同名的read()方法才能使用
AbstractList中的addAll()可以看做一个模板方法,他需要调用子类实现的add()方法。
HttpServlet 的 service() 函数也是一个模板方法,它需要调用同名的service()方法来实现功能,而同名service里再调用doGet/doPost等方法
Junit中的setUp/tearDown也是模板方法,先执行 setUp() 做些准备工作,然后执行 runTest() 运行真正的测试代码,最后执行 tearDown()扫尾。
我们写一个实际的例子,帮助大家理解。
java.util中有很多内置的容器类,大家都耳熟能详,那么他们的性能如何,你有测试过吗?初始化一个10000000的ArrayList和LinkedList哪个更快?
我们首先实现一个模板类,定义了元素个数和模板方法,统计初始化一个10000000元素的容器的耗时时长。
public abstract class Calculate { protected final int elementNum=10000000; /** * 统计method方法的时长 */ public final void templateMethod() { long s = System.currentTimeMillis(); method(); long e = System.currentTimeMillis(); System.out.format("start->end=%d\n",e-s); } protected abstract void method(); }
public class ArrayCalculate extends Calculate { @Override protected void method() { System.out.println(this.getClass().getSimpleName()); Integer[] integers = new Integer[elementNum]; for (int i = 0; i < elementNum; i++) { integers[i] = i; } } } // public class ArrayListCalculate extends Calculate { @Override protected void method() { System.out.println(this.getClass().getSimpleName()); ArrayList<Integer> integers = new ArrayList<>(); for (int i = 0; i < elementNum; i++) { integers.add(i); } integers.clear(); } } // public class LinkedListCalculate extends Calculate { @Override protected void method() { System.out.println(this.getClass().getSimpleName()); List<Integer> integers = new LinkedList<>(); for (int i = 0; i < elementNum; i++) { integers.add(i); } integers.clear(); } }
运行类
public class Main { public static void main(String[] args) { ArrayCalculate array = new ArrayCalculate(); array.templateMethod(); ArrayListCalculate arrayList = new ArrayListCalculate(); arrayList.templateMethod(); LinkedListCalculate linkedList = new LinkedListCalculate(); linkedList.templateMethod(); HashSetCalculate hashSet = new HashSetCalculate(); hashSet.templateMethod(); TreeSetCalculate treeSet = new TreeSetCalculate(); treeSet.templateMethod(); } }
输出:
ArrayCalculate start->end=2677 ArrayListCalculate start->end=945 LinkedListCalculate start->end=1044 HashSetCalculate start->end=3028 TreeSetCalculate start->end=2569
可以看出ArrayList相比原生数组还是有优势的!