如果你發現你有很多重複的**,你可能會考慮用模板方法消除容易出錯的重複**。這裡有乙個例子:下面的兩個類,完成了幾乎相同的功能:
例項化並初始化乙個reader來讀取csv檔案;
讀取每一行並解析;
把每一行的字元填充到product或customer物件;
將每乙個物件新增到set裡;
返回set。
正如你看到的,只有有注釋的地方是不一樣的。其他所有步驟都是相同的。
public class productcsvreader
}return returnset;
}}
public class customercsvreader
}return returnset;
}}
對於本例來說,只有兩個實體,但是乙個真正的系統可能有幾十個實體,所以有很多重複易錯的**。你可能會發現dao層有著相同的情況,在每個dao進行增刪改查的時候幾乎都是相同的操作,唯一與不同的是實體和表。讓我們重構這些煩人的**吧。根據gof設計模式第一部分提到的原則之一,我們應該「封裝不同的概念「productcsvreader和customercsvreader之間,不同的是有注釋的**。所以我們要做的是,把相同的放到乙個類,不同的抽取到另乙個類。我們先開始編寫productcsvreader,我們使用extract method提取帶注釋的部分:
public class productcsvreader
}return returnset;
}product unmarshall(string tokens)
}
現在我們已經把相同(重複)的**和不同(各自特有)的**分開了,我們要建立乙個父類abstractcsvreader,它包括兩個類(productreader和customerreader)相同的部分。我們把它定義為乙個抽象類,因為我們不需要例項化它。然後我們將使用pull up method重構這個父類。
abstract class abstractcsvreader
}return returnset;
}}
public class productcsvreader extends abstractcsvreader
}
如果在子類中沒有『unmarshall』方法,該類就無法進行編譯(它呼叫unmarshall方法),所以我們要建立乙個叫unmarshall的抽象方法。
abstract class abstractcsvreader
}return returnset;
}abstract product unmarshall(string tokens);
}
現在,在這一點上,abstractcsvreader是productcsvreader的父類,但不是customercsvreader的父類。如果customercsvreader繼承abstractcsvreader編譯會報錯。為了解決這個問題我們使用泛型。
abstract class abstractcsvreader
}return returnset;
}abstract t unmarshall(string tokens);
}
public class productcsvreader extends abstractcsvreader
}
public class customercsvreader extends abstractcsvreader
}
這就是我們要的!不再有重複的**!父類中的方法是「模板」,它包含這不變的**。那些變化的東西作為抽象方法,在子類中實現。記住,當你重構的時候,你應該有自動化的單元測試來保證你不會破壞你的**。我使用junit,你可以使用我帖在這裡的**,也可以在這個github庫找一些其他設計模式的例子。在結束之前,我想說一下模板方法的缺點。模板方法依賴於繼承,患有 the fragile base class problem。簡單的說就是,修改父類會對繼承它的子類造成意想不到的不良影響。事實上,基礎設計原則之一的gof設計模式提倡「多用組合少用繼承」,並且許多其他設計模式也告訴你如何避免**重複,同時又讓複雜或容易出錯的**盡量少的依賴繼承。歡迎交流,以便我可以提高我的部落格質量。
翻譯的不好,歡迎拍磚!
Java中泛型 使用
泛型 1.5 之後出現 提高安全 1 泛型 確定 集合容器的型別。2 接收一種資料型別,引用資料型別 arraylistlis new arraylist 目的 將執行時期的 錯誤 轉化到 編譯時期,提高了安全性!3 不需要 強制型別轉換.更加安全!泛型的擦除 泛型在編譯時期使用!使用完畢直接擦除。...
Java泛型使用詳解
一 泛型介面 1 第一種 在子類的定義上也宣告泛型型別。package com.xieke.generics.impl.demo1 inte ce info class infoimplimplements info public void setvar t var override public ...
Java 泛型的使用
需求 定義乙個字串集合,要求字串按照長度排序。在不使用泛型前,我們的 如下。public class genericdemo 自定義乙個比較器 class stringcomperator implements comparator 分析 我們可以觀察到,無論是在迭代器或者比較器,我們都需要進行強制...