模板方法模式
同步器的设计基于模板方法模式。模板方法模式的意图是,定义一个操作中的算法的骨架,而将一些步骤的实现延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。我们最常见的就是Spring框架里的各种Template。
例子:
我们开了个蛋糕店,我们决定先卖奶油蛋糕,芝士蛋糕和慕斯蛋糕。三种蛋糕在制作方式上一样,都包括造型,烘焙和涂抹蛋糕上的东西。所以可以定义一个抽象蛋糕模型:
/**
* 类说明:抽象蛋糕模型
*/
public abstract class AbstractCake {
protected abstract void shape();
protected abstract void apply();
protected abstract void brake();
/*模板方法*/
public final void run(){
this.shape();
this.apply();
this.brake();
}
}
然后就可以批量生产三种蛋糕:
/**
* 类说明:芝士蛋糕
*/
public class CheeseCake extends AbstractCake {
@Override
protected void shape() {
System.out.println("芝士蛋糕造型");
}
@Override
protected void apply() {
System.out.println("芝士蛋糕涂抹");
}
@Override
protected void brake() {
System.out.println("芝士蛋糕烘焙");
}
}
另外两种省略。
这样一来,不但可以批量生产三种蛋糕,而且如果日后有扩展,只需要继承抽象蛋糕方法就可以了,十分方便,我们天天生意做得越来越赚钱。
/**
* 类说明:生产蛋糕
*/
public class MakeCake {
public static void main(String[] args) {
AbstractCake cake1 = new CheeseCake();
AbstractCake cake2 = new CreamCake();
AbstractCake cake3 = new MousseCake();
cake1.run();
cake2.run();
cake3.run();
}
}
突然有一天,我们发现市面有一种最简单的小蛋糕销量很好,这种蛋糕就是简单烘烤成型就可以卖,并不需要涂抹什么食材,由于制作简单销售量大,这个品种也很赚钱,于是我们也想要生产这种蛋糕。但是我们发现了一个问题,抽象蛋糕是定义了抽象的涂抹方法的,也就是说扩展的这种蛋糕是必须要实现涂抹方法,这就很鸡儿蛋疼了。怎么办?我们可以将原来的模板修改为带钩子的模板:
/**
* 类说明:抽象蛋糕模型
*/
public abstract class AbstractCake {
protected abstract void shape();
protected abstract void apply();
protected abstract void brake();
/*模板方法*/
public final void run(){
this.shape();
if(this.shouldApply()){
this.apply();
}
this.brake();
}
protected boolean shouldApply(){
return true;
}
}
做小蛋糕的时候通过flag来控制是否涂抹,其余已有的蛋糕制作不需要任何修改可以照常进行:
/**
* 类说明:小蛋糕
*/
public class SmallCake extends AbstractCake {
private boolean flag = false;
public void setFlag(boolean shouldApply){
flag = shouldApply;
}
@Override
protected boolean shouldApply() {
return this.flag;
}
@Override
protected void shape() {
System.out.println("小蛋糕造型");
}
@Override
protected void apply() {
System.out.println("小蛋糕涂抹");
}
@Override
protected void brake() {
System.out.println("小蛋糕烘焙");
}
}