一、引言
场景:相信我们这个年龄的男人,绝大部分都会煮饭吧。那么我们通常通过加入水的多少来决定是煮粥、饭、硬饭、软饭。煮饭的步骤包括淘米、加水、淘好的米加适量的水(看自己的需求)放到电饭煲中煮就ok了。不管是煮饭、煮粥、软饭都包括上面的三步、唯一不同的就是加入的水的量。
如何用代码实现上面的场景呢?
思考与分析
1,不管是煮饭还是煮粥…都有重复的过程,就是淘米和放电饭煲上面煮,那么首先考虑的肯定要用到继承
2,不管是煮饭还是煮粥、都包括三个步骤1,淘米;2,加水;3,放电饭煲煮。这三个肯定是不变的。那么最好是定义一个通用的方法,包括这三个步骤
3,但是煮粥和煮饭、软饭…这里面的第二个步骤又不相同,那么考虑的就是在子类中重写这个方法,不同的子类有不同的实现。
4,父类中的这个“加水”的方法有没有必要实现呢?因为子类必然会重写这个方法,并且父类在非要实现这个方法,方法体中应该如何写呢?既然这样,干脆就让该方法是abstract类型的,让父类成为抽象类,不能实例化,让它的子类去重写这个方法。
结合上面的分析,那么模板设计模式就出来了
二、定义
模板模式:一个抽象类公开定义了执行它的方法的方式/模板。它的子类可能按照需要重写方法实现,但调用将以抽象类中定义的方式进行。定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定实现
三、uml图
四、代码实现
AbstractCook .java
package template;
/**
* 煮饭的抽象类
* @author hongtaolong
*
*/
public abstract class AbstractCook {
public void cook() {
washRice();
addWater();
putElectricBowl();
}
/**
* step1 淘米,不管煮饭,煮粥,硬饭,软饭,都是一样的
*/
private void washRice() {
System.out.println("淘米");
}
/**
* step2,加水,这一步是不一样的,硬饭,软饭、煮粥加的水是不一样的,延迟到子类去实现
*/
protected abstract void addWater() ;
/**
* step3,将装好水的米,放到电饭锅中煮饭
*/
private void putElectricBowl() {
System.out.println("将洗好米放到电饭锅中,开始煮...");
}
}
RiceCook .java
package template;
/**
* 煮饭
* @author hongtaolong
*
*/
public class RiceCook extends AbstractCook {
@Override
protected void addWater() {
// TODO Auto-generated method stub
System.out.println("煮饭,加入的水刚好淹没米一节小指头的长度");
}
}
GruelCook .java
package template;
/**
* 煮粥
* @author hongtaolong
*
*/
public class GruelCook extends AbstractCook {
@Override
protected void addWater() {
// TODO Auto-generated method stub
System.out.println("煮粥,水至少淹没过米三节手指头");
}
}
TemplateTestDemo .java
package template;
public class TemplateTestDemo {
public static void main(String[] args) {
//煮粥
AbstractCook riceCook = new RiceCook();
riceCook.cook();
System.out.println("------");
//煮饭
AbstractCook gruelCook = new GruelCook();
gruelCook.cook();
}
}
测试结果:
五、优缺点
1、优点
(1)提高代码复用性
(2)提高扩展性、只要实现不同的子类就行,符合开闭原则
(3)控制反转的原则,将实现延迟到子类
2、缺点
引用了抽象类,每个不同的实现都需要一个子类来实现,导致类的个数增加,从而增加了系统实现的复杂度
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/111234.html原文链接:https://javaforall.cn