喝飲料
平時我們喝茶或者喝咖啡一般經(jīng)歷以下四個步驟(星巴克等享受生活的土豪請稍微忍耐一下):
- 燒開水
- 用水沖泡
- 泡好之后倒入杯中
- 加入調(diào)料
我們可以寫出如下代碼:
public class Coffee {
public void start() {
prepare();
System.out.println("開始喝咖啡");
}
private void prepare() {
boil(); //燒水
brew(); //沖泡
poure(); //倒入
addCondiments(); //加入調(diào)料
}
private void boil() {
System.out.println("燒水");
}
private void brew() {
System.out.println("沖泡咖啡");
}
private void poure() {
System.out.println("倒入杯中");
}
private void addCondiments() {
System.out.println("加一些調(diào)料(糖等)");
}
}
代碼非常簡單,就是將上述過程描述了一遍。
現(xiàn)在如果我們想泡茶怎么辦?行吧,再寫一個Tea類。如下所示:
public class Tea {
public void start() {
prepare();
System.out.println("可以喝茶了");
}
private void prepare() {
boil(); //燒水
brew(); //沖泡
poure(); //倒入
addCondiments(); //加入調(diào)料
}
private void boil() {
System.out.println("燒水");
}
private void brew() {
System.out.println("沖泡茶葉");
}
private void poure() {
System.out.println("倒入杯中");
}
private void addCondiments() {
System.out.println("加一些調(diào)料");
}
}
看出一些端倪了吧,prepare()方法完全一樣,而且boil()和poure()方法也完全一樣。本著“不能大量出現(xiàn)重復(fù)代碼”的原則,怎么著也得想辦法抽象一下。
將喝飲料這個過程抽象一下
代碼如下:
//飲料類
public abstract class Beverage {
protected void prepare() {
boil(); //燒水
brew(); //沖泡
poure(); //倒入
addCondiments(); //加入調(diào)料
}
private void boil() {
System.out.println("燒水");
}
protected abstract void brew();
private void poure() {
System.out.println("倒入杯中");
}
protected abstract void addCondiments();
}
//改變后的咖啡類
public class Coffee extends Beverage {
public void start() {
prepare();
System.out.println("開始喝咖啡");
}
@Override
protected void brew() {
System.out.println("沖泡咖啡");
}
@Override
protected void addCondiments() {
System.out.println("加入調(diào)料糖");
}
}
//改變后的茶類
public class Tea extends Beverage {
public void start() {
prepare();
System.out.println("可以喝茶了");
}
@Override
protected void brew() {
System.out.println("沖泡茶葉");
}
@Override
protected void addCondiments() {
System.out.println("我喝茶不想加什么東西");
}
}
將相同的部分抽離到了抽象類中,子類繼承抽象類,實(shí)現(xiàn)一些抽象方法即可。但是這里不單單是抽象,注意到prepare()方法,這個方法里調(diào)用了其他方法,而且是有順序的調(diào)用,所以這個方法可以稱為“算法的框架”,也就是說這個方法僅僅是一個骨架,定義了各個步驟的順序,不過這些步驟的具體實(shí)現(xiàn)完全可以不一樣,甚至可以將實(shí)現(xiàn)推遲到子類實(shí)現(xiàn),由子類來決定該如何實(shí)現(xiàn),這就是“模板方法模式”。
模板方法模式特點(diǎn)
- 提高代碼復(fù)用。通過繼承將相同的代碼放入抽象基類中。
- 便于擴(kuò)展,比較靈活。當(dāng)需要新增子類的時候,只需要繼承抽象基類,然后重寫一些方法即可。
- 由于引入了抽象類,所以可能會導(dǎo)致子類非常多。
小結(jié)
現(xiàn)在可以給出模板方法模式的定義了:模板方法模式在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結(jié)構(gòu)的情況下,重新定義算法中的某些步驟
本系列文章參考書籍是《Head First 設(shè)計(jì)模式》,文中代碼示例出自書中。