模板模式
模板模式:一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,这种设计方式将一些步骤延迟到子类实现,但是子类却可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法为我们提供了一种代码复用的技巧,模板方法的抽象类可以定义具体方法、抽象方法和钩子。抽象方法由子类实现,钩子是一种方法,它可以不做任何事情,或者只做默认的事情,由子类决定是否覆盖这个方法。
下面举个例子来阐述一下这个设计模式。
比如说你和你对象去口渴了店里买饮料喝,一个要金桔柠檬,一个要珍珠奶茶。我们来想一下饮料的制作过程。
金桔柠檬: 珍珠奶茶:
1、把水倒入容器中 1、把水倒进容器
2、加柠檬 、椰果等 2、加调料(奶茶、珍珠等)
3、搅拌 3、搅拌
我们来用代码实现这些操作步骤:
/** * 金桔柠檬 */ public class Lemon { //倒水 public void pourWater(){}; //加柠檬 public void pourLemon(){}; //搅拌 public void stir(){} } /** * 奶茶 */ public class MilkTea { //倒水 public void pourWater(){}; //加珍珠 public void pourPearl(){}; //搅拌 public void stir(){} }
金桔柠檬和奶茶的制作有相同的地方,我们把这些共性进一步抽象,定义一个抽象类,将这些共性的东西,比如说倒水喝搅拌的动作,不希望子类修改的用final来修饰,而放调料由子类决定需要哪些调料,定义成抽象的方法,让子类必须去实现它。
public abstract class MakeDrink { //倒水 public final void pourWater(){ }; //搅拌 public final void stir(){}; //加调料 public abstract void putSomething(); } /** * 奶茶 */ public class MilkTea extends MakeDrink{ @Override public void putSomething() { System.out.println("放珍珠"); } } /** * 金桔柠檬 */ public class Lemon extends MakeDrink{ @Override public void putSomething() { System.out.println("放柠檬"); } }
这就是一个简单的模板模式的应用。
好的,饮料制作好了,服务人员问你是打包还是现在就喝,你的对象说打包,但是你现在就想喝,那么可以在定义一个默认的方法,做一些默认的事情,比如说给你包装好,喝不喝随你,你可以重写这个方法,也可以选着不重写,这就是钩子。
我们在抽象类里面再加个打包的方法,Lemon类重写这个方法,而MilkTea采用父类默认的方法。
public abstract class MakeDrink { //倒水 public final void pourWater(){ }; //搅拌 public final void stir(){}; public abstract void putSomething(); public void packageDrink(){ System.out.println("打包好了"); } } /** * 金桔柠檬 */ public class Lemon extends MakeDrink{ @Override public void putSomething() { System.out.println("放柠檬"); } @Override public void packageDrink(){ System.out.println("我现在就喝"); } }
我们平时代码开发经常用到这种模式,一些框架用到的也非常多,像Spring的JDBCTemplate。使用模板模式能够将代码的复用最大化,算法只存在于一个地方,容易修改。