在瞭解“模板設計模式”之前要先了解關於抽象類的相關概念:
-
抽象類的定義與使用
a)定義:抽象類只是比普通類多了一些抽象方法
b)抽象方法:只聲名而未實現的方法(沒有方法體),抽象方法必須使用abstract關鍵字類定義。並且抽象方法所在的類也一定要使用abstract來定義 -
抽象類的使用原則
a)所有抽象類必須有子類
b)抽象類的子類必須覆寫抽象類的所有抽象方法
c)抽象類無法直接創建實例化對象,需要通過子類向上轉型爲其實例化 -
抽象類的相關約定
a)抽象類一定存在構造方法,子類也一定遵循對象實例化流程。先調用父類構造,再調用子類構造
b)抽象類可以沒有任何抽象方法,但此時仍然不能直接創建實例化對象
c)final與abract,private與abract不能同時出現
以上是關於抽象類的一些基本概念
關於抽象類的詳細內容可以參考:https://mp.csdn.net/postedit/103091095
如果現在需要實現*“沖泡牛奶和沖泡果汁”*的功能,用普通方法可能會這樣實現:
class Milk{
void prepareRecipe(){
boilWater();
brewMilk();
pourIncup();
addSugar();
}
void boilWater(){
System.out.println("boil water");
}
void brewCoffee(){
System.out.println("brew milk");
}
void pourIncup(){
System.out.println("pour in cup");
}
void addSugar(){
System.out.println("add suger");
}
}
class Juice{
void prepareRecipe(){
boilWater();
brewJuice();
pourIncup();
addLemon();
}
void boilWater(){
System.out.println("boil water");
}
void brewJuice(){
System.out.println("brew juice");
}
void pourIncup(){
System.out.println("pour in cup");
}
void addLemon(){
System.out.println("add lemon");
}
}
public class Drink {
public static void main(String[] args) {
Milk milk = new Milk();
milk.prepareRecipe();
Juice juice = new Juice();
juice.prepareRecipe();
}
}
如上述代碼所示,這樣寫下來重複代碼很多,代碼複用率很少,程序的可擴展性也不好,如果想要在增加沖泡其他類似東西,相似的代碼又得重新寫一遍,因此使用“模板設計模式”對以上代碼進行修改.
那麼什麼是“模板設計模式”呢?
模板(模板方法)設計模式:
基於抽象類,在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。
模板模式可以使得子類在不改變算法的前提下,重新定義算法中的某些步驟
這樣的說法有點抽象,實際上就是將核心部分的算法進行封裝,讓子類結合自己所需繼承或修改相應的方法,這樣就使得代碼複用率高,邏輯性強,彈性高
結合到“沖泡牛奶和沖泡果汁”這個例子來講,就是把沖泡這兩樣東西都要經歷的過程(例如:boilwater(),pourIncup())提煉出來,將兩者不同的部分(例如:addLemon()/addsuger())用抽象方法實現,這樣子類繼承的時候就可以根據自己的需求來覆寫相應的方法,代碼複用率大大提高。
那麼如果是一個飲品店使用到上述的方法時,可能會面臨有的顧客想加輔料,而有的顧客不想加相應的輔料,此時就要根據顧客的需求來決定是否加輔料,所以我們引進了
鉤子方法,根據需求選擇是否掛鉤,意思就是需要加輔料的時候才加相應輔料。
以上內容的實現代碼如下所示:
abstract class Moudle{
final void prepareRecipe(){
boilWater();
brewSomething();
pourIncup();
if(custmersWantCondiments()) {
addSomething();
}
}
final void boilWater() {
System.out.println("boil water");
}
abstract void brewSomething();
private void pourIncup() {
System.out.println("pour in cup");
}
abstract void addSomething();
//鉤子方法
boolean custmersWantCondiments(){
return true;
}
}
class Milk1 extends Moudle{
@Override
void brewSomething() {
System.out.println("brew milk");
}
@Override
void addSomething() {
System.out.println("add suger");
}
boolean custmersWantCondiments() {
System.out.println("do you need some suger ? y/n");
String result = getUserInfo();
if(result.equals("y") ){
return true;
}else {
return false;
}
}
private String getUserInfo() {
Scanner scanner = new Scanner(System.in);
String info = scanner.next();
return info;
}
}
class Juice extends Moudle{
@Override
void brewSomething() {
System.out.println("brew juice");
}
@Override
void addSomething() {
System.out.println("add leamon");
}
}
public class DrinkMoudle {
public static void main(String[] args) {
Milk1 milk = new Milk1();
milk.prepareRecipe();
Juice1 juice = new Juice1();
juice.prepareRecipe();
}
}
設計模式的核心原則是開閉原則
開閉原則(OCP):一個軟件實體如類,模塊或函數應該對擴展開放,對修改關閉
上述的模板設計模式就遵循了此原則,對於核心的方法用final修飾,這樣就保障了子類可以使用但不可以修改,提高了安全性