學習模板方法模式,讓我想到了貝爺喫蟲子

模板方法模式是什麼?

定義一個方法,這個方法不能被子類複寫 但是可以被子類調用。在這個方法裏規定了算法流程或者方法調用順序。按照這種想法實現的就叫模板方法模式。

案例展示

說總是模糊,給你看更清晰!

假設咱們來總結一下貝爺喫昆蟲的節目,然後用模板方法模式做個小案例。
我們來分析一下貝爺,喫昆蟲的流程:

  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();
	}
}

運行結果:

荒野求生節目,現在開始!
----------
貝爺,抓住了一個螞蚱!
去頭
擠出內臟
一口吞下
味道像雞肉,還不錯!
----------
貝爺,捉到一隻天牛幼蟲!
去頭
擠出內臟
一口吞下
這條蟲,是我喫過最難喫的東西之一
----------
貝爺,抓住了一條蚯蚓!
一口吞下
這玩意,味道出乎意料,有點像意大利麪

優點:

通過鉤子函數我們可以控制一些方法是否調用。增加了可用性。

缺點:

當需要變化的太多時,如果每個都需要加鉤子函數,那就是去了模板的意義。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章