今天这篇博客将向大家介绍一种新的设计模式,可能该设计模式大家以前在项目里面经常用到过,但是却不知道具体是叫什么名字。我们现在看看模板方法模式的定义是怎样的:定义一个操作中的算法框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。看着好像挺绕口的,那么下面笔者将通过一个例子来具体的分析一下。
比如今天笔者突然厨艺大发,想要好好地给老婆做两道菜,一道是尖椒肉丝,一道是鱼香肉丝。在做这两道菜的过程中,笔者发现都需要经过以下几个步骤:洗菜->切菜->开炒->放调料->起锅。下面我们能不能通过代码来完整的模拟出这两道菜的烹饪过程呢?请看下面的类图:
通过上面的类图,我们发现其实实现过程很简单,笔者只是定义了一个蔬菜模板类,然后分别扩展出两个菜类,请看代码实现。
首先,我们来定义出基类:
abstract class VegetModel { protected abstract void washVeget(); protected abstract void cutVeget(); protected abstract void cookVeget(); protected abstract void sensorVeget(); protected abstract void potVeget(); }
然后我们再来分别实现两个扩展类:
public class Veget1Model1 extends VegetModel { @Override protected void washVeget() { // TODO Auto-generated method stub } @Override protected void cutVeget() { // TODO Auto-generated method stub } @Override protected void cookVeget() { // TODO Auto-generated method stub } @Override protected void sensorVeget() { // TODO Auto-generated method stub } @Override protected void potVeget() { // TODO Auto-generated method stub } public void startCook(){ washVeget(); cutVeget(); cookVeget(); sensorVeget(); potVeget(); } }
public class Veget2Model2 extends VegetModel { @Override protected void washVeget() { // TODO Auto-generated method stub } @Override protected void cutVeget() { // TODO Auto-generated method stub } @Override protected void cookVeget() { // TODO Auto-generated method stub } @Override protected void sensorVeget() { // TODO Auto-generated method stub } @Override protected void potVeget() { // TODO Auto-generated method stub } public void startCook(){ washVeget(); cutVeget(); cookVeget(); sensorVeget(); potVeget(); } }
好了,上面的两个扩展类都已经实现出来了,但是细心的读者可能会发现上面两段代码存在很大的冗余,那就是都有startCook方法。当出现冗余方法的时候,作为代码的设计者就应该考虑重构、调整设计了。那么我们应该怎么消除这段代码带来的臭味呢?其实我们可以将startCook方法放到基类里面,这样代码接口如下:
abstract class VegetModel { protected abstract void washVeget(); protected abstract void cutVeget(); protected abstract void cookVeget(); protected abstract void sensorVeget(); protected abstract void potVeget(); protected void startCook(){ washVeget(); cutVeget(); cookVeget(); sensorVeget(); potVeget(); } }
这下就可以很好的避免掉冗余的问题,这就是模板方法模式,是不是很简单呢?我们在项目里面肯定会经常使用到。下面我们再来看看模板方法模式的扩展,请看下面的情景,如果我在炒尖椒肉丝的过程中发现粘锅了,需要放点水,但是鱼香肉丝我有不希望做的太水。这个时候我们应该怎么办呢?我们需要在基类模板里面留一个钩子方法,通过钩子方法我们就能够很好的区分是否放水的情况。调整之后的代码如下:
abstract class VegetModel { protected abstract void washVeget(); protected abstract void cutVeget(); protected abstract void cookVeget(); protected abstract void sensorVeget(); protected abstract void potVeget(); protected abstract void putWater(); protected void startCook(){ washVeget(); cutVeget(); cookVeget(); sensorVeget(); if(isWater()){ putWater(); } potVeget(); } protected abstract boolean isWater(); }
然后子类里面修改的部分为:
@Override protected boolean isWater() { return isWater; } public void setWater(boolean isWater) { this.isWater = isWater; } @Override protected void putWater() { // TODO Auto-generated method stub }
外部通过调用setWater方法就可以控制是否放水了。
好了,今天的博客就到这里吧!see you!