摘要:模板方法模式定義定義抽象類并且聲明一些抽象基本方法供子類實現不同邏輯,同時在抽象類中定義具體方法把抽象基本方法封裝起來,這就是模板方法模式。
近日,ofo小黃車宣布入駐法國巴黎,正式進入全球第20個國家,共享單車已然改變了我們的出行方式。就拿我自己來說,每當下班出地鐵的第一件事,以光速鎖定一輛共享單車,百米沖刺的速度搶在別人之前占領它。
而大家都是重復著同樣的動作,拿出手機開鎖、騎車、上鎖、結算,哇~這是何等壯觀的場景,甚至還有的不用開鎖直接把車騎走的,鎖壞了嘛。
為什么要用模板方法模式
現在共享單車以開鎖的方式來分,一般有掃碼開鎖和密碼開鎖兩種,來看共享單車使用流程的實現。
正常的思維邏輯是,抽象一個父類,子類繼承父類并實現父類方法。OK,看抽象類代碼:
public abstract class AbstractClass {
// 開鎖 public abstract void unlock(); // 騎行 public abstract void ride(); // 上鎖 public abstract void lock(); // 結算 public abstract void pay(); // 用戶使用 public abstract void use();
}
抽象類定義了我們使用共享單車的幾個基本流程,現在有兩種不同開鎖方式單車的使用,都繼承抽象類,代碼如下:
//
public class ScanBicycle extends AbstractClass {
@Override public void unlock() { System.out.println("掃碼開鎖"); } @Override public void ride() { System.out.println("騎起來很拉風"); } @Override public void lock() { System.out.println("上鎖"); } @Override public void pay() { System.out.println("結算"); } @Override public void use() { unlock(); ride(); lock(); pay(); }
}
以上是通過掃碼方式開鎖騎行,再來看密碼開鎖騎行,代碼如下:
public class CodeBicycle extends AbstractClass {
@Override public void unlock() { System.out.println("密碼開鎖"); } @Override public void ride() { System.out.println("騎起來很拉風"); } @Override public void lock() { System.out.println("上鎖"); } @Override public void pay() { System.out.println("結算"); } @Override public void use() { unlock(); ride(); lock(); pay(); }
}
好了,兩種方式都定義好了,看客戶端的調用:
public class Client {
public static void main(String[] args) { ScanBicycle scanBicycle = new ScanBicycle(); scanBicycle.use(); System.out.println("========================"); CodeBicycle codeBicycle = new CodeBicycle(); codeBicycle.use(); }
}
結果如下:
掃碼開鎖
騎起來很拉風
上鎖
掃碼開鎖
騎起來很拉風
上鎖
結算
相信都已經看出代碼的問題,use方法的實現是一樣的,也就是代碼重復了,這是病必須得治,藥方就是模板方式模式。
模板方法模式
定義
??定義抽象類并且聲明一些抽象基本方法供子類實現不同邏輯,同時在抽象類中定義具體方法把抽象基本方法封裝起來,這就是模板方法模式。
UML
模板方法模式
模板方法模式涉及到的角色有兩個角色:
抽象模板角色:定義一組基本方法供子類實現,定義并實現組合了基本方法的模板方法。
具體模板角色:實現抽象模板角色定義的基本方法
模板方法模式還涉及到以下方法的概念:
基本方法
抽象方法:由抽象模板角色聲明,abstract修飾,具體模板角色實現。
鉤子方法:由抽象模板角色聲明并實現,具體模板角色可實現加以擴展。
具體方法:由抽象模板角色聲明并實現,而子類并不實現。
模板方法
抽象模板角色聲明并實現,負責對基本方法的調度,一般以final修飾,不允許具體模板角色重寫。模板方法一般也是一個具體方法。
模式實戰
利用模板方式模式對上面的代碼進行重構,來看抽象模板角色,代碼如下:
public abstract class AbstractClass {
protected boolean isNeedUnlock = true; // 默認需要開鎖 /** * 基本方法,子類需要實現 */ protected abstract void unlock(); /** * 基本方法,子類需要實現 */ protected abstract void ride(); /** * 鉤子方法,子類可實現 * * @param isNeedUnlock */ protected void isNeedUnlock(boolean isNeedUnlock) { this.isNeedUnlock = isNeedUnlock; } /** * 模板方法,負責調度基本方法,子類不可實現 */ public final void use() { if (isNeedUnlock) { unlock(); } else { System.out.println("========鎖壞了,不用解鎖========"); } ride(); }
}
抽象模板角色定義了unlock和ride兩個使用單車的基本方法,還有一個鉤子方法,用來控制模板方法邏輯順序,核心是use模板方法,用final修飾,該方法完成對基本方法調度。注意,模板方法中對基本方法的調度是有順序有規則的。還有一點,基本方法都是protected修飾的,因為基本方法都是在以public修飾的模板方法中調用,并且可以由子類實現,并不需要暴露給其他類調用。
現在來看兩個具體模板角色的實現:
// 掃碼開鎖的單車
public class ScanBicycle extends AbstractClass {
@Override protected void unlock() { System.out.println("========" + "掃碼開鎖" + "========"); } @Override protected void ride() { System.out.println(getClass().getSimpleName() + "騎起來很拉風"); } protected void isNeedUnlock(boolean isNeedUnlock) { this.isNeedUnlock = isNeedUnlock; }
}
// 密碼開鎖的單車
public class CodeBicycle extends AbstractClass {
@Override protected void unlock() { System.out.println("========" + "密碼開鎖" + "========"); } @Override protected void ride() { System.out.println(getClass().getSimpleName() + "騎起來很拉風"); } protected void isNeedUnlock(boolean isNeedUnlock) { this.isNeedUnlock = isNeedUnlock; }
}
可以看到,相比之前的實現,現在兩個具體類都不需要實現use方法,只負責實現基本方法的邏輯,職責上變得更加清晰了。來看用戶如何使用:
public class Client {
public static void main(String[] args) { ScanBicycle scanBicycle = new ScanBicycle(); scanBicycle.use(); CodeBicycle codeBicycle = new CodeBicycle(); codeBicycle.use(); }
}
運行結果如下:
========掃碼開鎖========
ScanBicycle騎起來很拉風
========密碼開鎖========
CodeBicycle騎起來很拉風
當我以百米沖刺的速度跑到共享單車面前時,發現這輛車的鎖是壞掉的,也就是不用開鎖,免費的,騎回家收藏也沒問題。在代碼中只要調用鉤子方法isNeedUnlock就好,實現如下:
public class Client {
public static void main(String[] args) { ScanBicycle scanBicycle = new ScanBicycle(); scanBicycle.isNeedUnlock(false); scanBicycle.use(); CodeBicycle codeBicycle = new CodeBicycle(); codeBicycle.isNeedUnlock(true); codeBicycle.use(); }
}
運行結果如下:
========鎖壞了,不用解鎖========
ScanBicycle騎起來很拉風
========密碼開鎖========
CodeBicycle騎起來很拉風
上面提到模板方法對基本方法的調度是有順序的,也就是說模板方法中的邏輯是不可變的,子類只實現可以被實現的基本方法,但不會改變模板方法中的頂級邏輯。而鉤子方法的使用只是對模板方法中邏輯的控制,影響的是模板方法的結果,并不會改變原有邏輯。
模板方法模式的優缺點
優點
1)良好的封裝性。把公有的不變的方法封裝在父類,而子類負責實現具體邏輯。
2)良好的擴展性:增加功能由子類實現基本方法擴展,符合單一職責原則和開閉原則。
3)復用代碼。
缺點
1)由于是通過繼承實現代碼復用來改變算法,靈活度會降低。
2)子類的執行影響父類的結果,增加代碼閱讀難度。
總結
模板方法模式看上去簡單,但是整個模式涉及到的都是面向對象設計的核心,比如繼承封裝,基于繼承的代碼復用,方法的實現等等。當中還有涉及到一些關鍵詞的使用,也是我們Java編程中需要掌握的基礎。總體來說,模板方法模式是很好的學習對象。下一篇是中介者模式,您的點贊和關注是我的動力,再會!
更多精彩干貨關注“AndroidJet的開發之路”公眾號
設計模式Java源碼GitHub下載:https://github.com/jetLee92/D...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68265.html
摘要:咦這一層一層上報就涉及到這次的責任鏈模式。責任鏈模式和觀察者模式存在一個共同點,就是傳遞責任鏈模式是一級一級的傳遞,形成一條鏈,鏈節點處理者之間是存在傳遞關系的。這是責任鏈模式和觀察者模式的區別,也是責任鏈模式的核心。 今天來說說程序員小猿和產品就關于需求發生的故事。前不久,小猿收到了產品的需求。 產品經理:小猿,為了迎合大眾屌絲用戶的口味,我們要放一張圖,要露點的。 小猿:........
摘要:看起來沒有集合框架,線程,等那么耀眼,但它可是很多框架的基礎啊回復反射查看相關文章,先把基礎學會,后面的得用到它。 回頭看看, 我進入Java 領域已經快15個年頭了, 雖然學的也一般, 但是分享下我的心得,估計也能幫大家少走點彎路。[入門]我在2001年之前是C/C++陣營, 有C和面向對象的基礎, 后來轉到Java ,發現沒有指針的Java真是好簡單, 另外Java 的類庫好用的讓...
摘要:會一直完善下去,歡迎建議和指導,同時也歡迎中用到了那些設計模式中用到了那些設計模式這兩個問題,在面試中比較常見。工廠設計模式使用工廠模式可以通過或創建對象。 我自己總結的Java學習的系統知識點以及面試問題,已經開源,目前已經 41k+ Star。會一直完善下去,歡迎建議和指導,同時也歡迎Star: https://github.com/Snailclimb... JDK 中用到了那...
閱讀 1768·2021-11-11 16:55
閱讀 2571·2021-08-27 13:11
閱讀 3631·2019-08-30 15:53
閱讀 2305·2019-08-30 15:44
閱讀 1394·2019-08-30 11:20
閱讀 1042·2019-08-30 10:55
閱讀 949·2019-08-29 18:40
閱讀 3037·2019-08-29 16:13