学习模板方法模式,让我想到了贝爷吃虫子

模板方法模式是什么?

定义一个方法,这个方法不能被子类复写 但是可以被子类调用。在这个方法里规定了算法流程或者方法调用顺序。按照这种想法实现的就叫模板方法模式。

案例展示

说总是模糊,给你看更清晰!

假设咱们来总结一下贝爷吃昆虫的节目,然后用模板方法模式做个小案例。
我们来分析一下贝爷,吃昆虫的流程:

  1. 抓虫子
  2. 去头
  3. 去内脏
  4. 一口吞
  5. 点评一波

下边在咱们就按照这个模板来做个模板方法小案例

昆虫——父类、模板方法所在类

package 模板方法模式;

public abstract class 昆虫 {
	/**
	 * 模板方法,吃昆虫,模板方法做成final,不让子类复写
	 */
	final void eatInsect() {
		 grab();
		 decapitation();
		 gutted();
		 eat();
		 evaluation();
	}
	/**
	 * 抓虫子
	 * 抽象方法,具体由子类实现(抓什么虫子)
	 */
 	abstract void grab();
 	/**
 	 * 去头
 	 */
	void decapitation() {
		System.out.println("去头");
	}
	/**
	 * 去除内脏
	 */
	void gutted() {
		System.out.println("挤出内脏");
	}
	
	void eat() {
		System.out.println("一口吞下");
	}
	/**
	 * 吃完虫子后的评价——抽象方法
	 */
 	abstract void evaluation();
}


然后写具体的子类

蚂蚱

package 模板方法模式;

public class 蚂蚱 extends 昆虫{

	@Override
	void grab() {
		System.out.println("贝爷,抓住了一个蚂蚱!");
	}

	@Override
	void evaluation() {
		System.out.println("味道像鸡肉,还不错!");
	}
	
}

天花幼虫

package 模板方法模式;

public class 天牛幼虫 extends 昆虫{

	@Override
	void grab() {
		System.out.println("贝爷,捉到一只天牛幼虫!");
	}

	@Override
	void evaluation() {
		System.out.println("这条虫,是我吃过最难吃的东西之一");
	}
	
}

接下来开始重点戏:贝爷开始吃虫

贝爷

package 模板方法模式;

public class 贝爷 {
	public static void main(String[] args) {
		System.out.println("荒野求生节目,现在开始!");
		System.out.println("----------");
		昆虫 grasshopper = new 蚂蚱();
		grasshopper.eatInsect();
		System.out.println("----------");
		昆虫 beetleLarvae = new 天牛幼虫();
		beetleLarvae.eatInsect();
		
	}
}

运行结果:

荒野求生节目,现在开始!
----------
贝爷,抓住了一个蚂蚱!
去头
挤出内脏
一口吞下
味道像鸡肉,还不错!
----------
贝爷,捉到一只天牛幼虫!
去头
挤出内脏
一口吞下
这条虫,是我吃过最难吃的东西之一

优点分析:

我们可以看到上边定义了吃虫子方法的模板后,具体到某个虫子,只需要再写一点点代码,然后调用模板方法就可以了。

缺点分析:

他的优势也是他的弱势,当子类具体方法各不相同时,写这个模板不仅没用还麻烦。

代码问题:

经常看荒野求生的人应该知道,贝爷吃过的虫子还有蚯蚓!!没有去头!没有挤出内脏,那怎么办呢?
使用钩子函数,其实就是调用方法时加一个** if **的事,true就条用,false就不调用。
下面咱们改善一下代码。

改善版:

昆虫:

package 模板方法模式.improve;

public abstract class 昆虫 {
	/**
	 * 模板方法,吃昆虫,模板方法做成final,不让子类复写
	 */
	final void eatInsect() {
		 grab();
		 if(needDecapitation()) {
			 decapitation();
		 }
		 if(needGutted()) {
			 gutted();
		 }
		 eat();
		 evaluation();
	}
	/**
	 * 钩子函数,确定是否需要去头
	 * @return
	 */
	public boolean needDecapitation() {
		return true;
	}
	/**
	 * 钩子函数,决定是否需要去内脏
	 * @return
	 */
	public boolean needGutted() {
		return true;
	}
	/**
	 * 抓虫子
	 * 抽象方法,具体由子类实现(抓什么虫子)
	 */
 	abstract void grab();
 	/**
 	 * 去头
 	 */
	void decapitation() {
		System.out.println("去头");
	}
	/**
	 * 去除内脏
	 */
	void gutted() {
		System.out.println("挤出内脏");
	}
	
	void eat() {
		System.out.println("一口吞下");
	}
	/**
	 * 吃完虫子后的评价——抽象方法
	 */
 	abstract void evaluation();
}

因为钩子函数默认返回的是true,所以在蚂蚱、天牛幼虫实现时,不用做任何改变。而蚯蚓就需要复写一下钩子函数的代码了。

蚯蚓

package 模板方法模式.improve;

public abstract class 昆虫 {
	/**
	 * 模板方法,吃昆虫,模板方法做成final,不让子类复写
	 */
	final void eatInsect() {
		 grab();
		 if(needDecapitation()) {
			 decapitation();
		 }
		 if(needGutted()) {
			 gutted();
		 }
		 eat();
		 evaluation();
	}
	/**
	 * 钩子函数,确定是否需要去头
	 * @return
	 */
	public boolean needDecapitation() {
		return true;
	}
	/**
	 * 钩子函数,决定是否需要去内脏
	 * @return
	 */
	public boolean needGutted() {
		return true;
	}
	/**
	 * 抓虫子
	 * 抽象方法,具体由子类实现(抓什么虫子)
	 */
 	abstract void grab();
 	/**
 	 * 去头
 	 */
	void decapitation() {
		System.out.println("去头");
	}
	/**
	 * 去除内脏
	 */
	void gutted() {
		System.out.println("挤出内脏");
	}
	
	void eat() {
		System.out.println("一口吞下");
	}
	/**
	 * 吃完虫子后的评价——抽象方法
	 */
 	abstract void evaluation();
}

再让贝爷吃一波看看

贝爷

package 模板方法模式.improve;

public class 贝爷 {
	public static void main(String[] args) {
		System.out.println("荒野求生节目,现在开始!");
		System.out.println("----------");
		昆虫 grasshopper = new 蚂蚱();
		grasshopper.eatInsect();
		System.out.println("----------");
		昆虫 beetleLarvae = new 天牛幼虫();
		beetleLarvae.eatInsect();
		System.out.println("----------");
		昆虫 earthworm = new 蚯蚓();
		earthworm.eatInsect();
	}
}

运行结果:

荒野求生节目,现在开始!
----------
贝爷,抓住了一个蚂蚱!
去头
挤出内脏
一口吞下
味道像鸡肉,还不错!
----------
贝爷,捉到一只天牛幼虫!
去头
挤出内脏
一口吞下
这条虫,是我吃过最难吃的东西之一
----------
贝爷,抓住了一条蚯蚓!
一口吞下
这玩意,味道出乎意料,有点像意大利面

优点:

通过钩子函数我们可以控制一些方法是否调用。增加了可用性。

缺点:

当需要变化的太多时,如果每个都需要加钩子函数,那就是去了模板的意义。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值