第十篇:模板方法模式

我们先来谈谈 "模板" 的概念,什么是模板? 很简单嘛,直接上图!



这就是一个模板!它定义了基本的样式,整个文档结构,内容大纲,而你要做的,就是再某些地方写上自己的内容就可以了! 让我们用代码来举一个模板方法的例子吧!

我们拟定一个炒米粉的过程(因为我今天吃的是米粉),首先,要刷锅,然后放油,放入粉条,翻炒, 放盐,接下来可以选择放醋,放辣椒,放葱, 然后起锅放入碗中, 自此整个流程完毕!

我们来分析一下这个过程:


通过画图,我们发现,其中某些步骤是完全固定的,那我们就可以思考,是不是可以有一个类,然后定义一个总的方法,这个方法就像是一个大的算法(把炒米粉看成是一个算法吧)骨架,或者说它就是一个模板,在这个方法中,它顺序调用不同的方法(步骤) , 先调用刷锅(),再放油()...接下来要解决放粉条的问题,怎么办,它自己不知道要放什么粉条,OK,抽象嘛,让子类来决定要放什么粉条咯!  再接下来要放醋...到底放不放呢? 放醋的过程是固定的,我们要复用这段代码,那怎么办呢? 那具体放醋过程还是我们父类自己觉得,而到底要不要放我们则可以问一下子类嘛!当它回答说不放,那就不放!

Ok,思路已经很清晰了!我们来让代码说话吧!

先来几个面和粉的对象...

/**所有粉条父类*/
public abstract class Flour {
	protected String name ;

	public String getName() {return name;}
	public void setName(String name) {this.name = name;}
}

/**挂面*/
class NoodlesFlour extends Flour{
	public NoodlesFlour() {
		this.name = "挂面";
	}
}
/**米粉*/
class RiceFlour extends Flour{
	public RiceFlour() {
		this.name = "米粉";
	}
}

 接下来定义我们的模板类!

/**定义一个炒粉抽象模板方法类*/
abstract class AbstractFryFlourTemplate{
	
	//定义为final,因为算法过程(炒粉过程)是固定的!我希望算法过程不被子类覆盖!
	public final void startFry(){
		rinse();
		addOil();
		addFlour();
		roll();
		addSalt();
		
		//仔细看看,这部分像不像是一个钩子?
		if( isAddVinegar() ){
			addVinegar();
		}
		if( isAddPepper() ){
			addPepper();
		}
		
		addToBowl();
	}
	
	private final void rinse(){
		System.out.println("刷锅...");
	}
	private final void addOil(){
		System.out.println("放点油...");
	}
	//抽象方法,放入米粉
	protected abstract void addFlour();
	
	//翻炒方法,子类可以根据炒法不同而进行覆盖
	protected void roll(){
		System.out.println("默认慢慢的炒...");
	}
	private final void addSalt(){
		System.out.println("放点盐...");
	}
	
	//放醋方法
	private final void addVinegar(){
		System.out.println("打开醋瓶");
		System.out.println("放点醋...");
		System.out.println("关好醋瓶");
	} 
	
	//放辣椒方法
	private final void addPepper(){
		System.out.println("放点辣椒!");
	} 
	
	private final void addToBowl(){
		System.out.println("放到碗里去...");
	}
	
	//到底放不放醋,子类可以来做决定,但我们默认放!
	protected boolean isAddVinegar(){
		return true;
	}
	
	//到底放不放辣椒,必须子类做出决定,也就是必须问下客户,您要辣椒不?
	protected abstract boolean isAddPepper();
}

再定义两个不同的算法类...

/**炒面的类*/
class FlyNoodlesFlour extends AbstractFryFlourTemplate{
	@Override
	protected void addFlour() {
		Flour flour = new NoodlesFlour();
		System.out.println("放入:"+flour.getName());
	}

	//客人说要放辣椒
	@Override
	protected boolean isAddPepper() {
		return true;
	}
	//覆盖翻炒方法,我是高级厨师...
	@Override
	protected void roll() {
		System.out.println("各种花样百出的炒...");
	}
}

/**炒粉的类*/
class FlyRiceFlour extends AbstractFryFlourTemplate{
	@Override
	protected void addFlour() {
		Flour flour = new RiceFlour();
		System.out.println("放入:"+flour.getName());
	}

	//客人说不要放辣椒
	@Override
	protected boolean isAddPepper() {
		return false;
	}
	
	//客人还说也不要放醋
	@Override
	protected boolean isAddVinegar() {
		return false;
	}
}

测试一下:

public class Test {
	
	public static void main(String[] args) {
		AbstractFryFlourTemplate aft = new FlyNoodlesFlour();
		aft.startFry();
		
		System.out.println("*****************************");
		AbstractFryFlourTemplate aft2 = new FlyRiceFlour();
		aft2.startFry();
	}
}

输出:*******************************************************************

刷锅...
放点油...
放入:挂面
各种花样百出的炒...
放点盐...
打开醋瓶
放点醋...
关好醋瓶
放点辣椒!
放到碗里去...
*****************************
刷锅...
放点油...
放入:米粉
默认慢慢的炒...
放点盐...
放到碗里去...

**************************************************************************


Ok,我们来分析一下上面的代码吧!AbstractFryFlourTemplate类定义了一个统一的炒面粉的模板,可以把它看做事一个算法骨架,一个框架;  我们看到,它完成一个算法的流程是固定的,但某些流程它无法自己完成,所以定义为抽象的,让子类去完成, 更有趣的是,它定义了两个钩子方法,钩子方法有默认值,也就是这个算法默认就会这么去做,当然它也允许子类去决定到底要不要这样做,比如要不要放醋; 这一点,我们可以说成是, 通过定义钩子方法,模板类可以让子类参与和改变算法的某些执行过程!


最后,我们来定义一下模板方法: 在一个方法中定义一个算法的骨架,但它允许将某些执行内容延迟到子类去执行; 通过钩子方法,它允许子类改变算法的执行过程!





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值