日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

使用Java泛型的模板方法模式示例

發(fā)布時間:2023/12/3 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Java泛型的模板方法模式示例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

如果發(fā)現(xiàn)除了某些部分外,您的許多例程完全相同,那么您可能需要考慮使用Template Method來消除容易出錯的代碼重復 。 這是一個示例:下面是兩個做類似事情的類:

  • 實例化并初始化Reader以從CSV文件讀取。
  • 閱讀每一行并將其分解為令牌。
  • 將每行中的令牌解組到一個實體(產品或客戶)中。
  • 將每個實體添加到集合中。
  • 返回集合。
  • 正如您所看到的,只有在第三步中才有所不同–將編組到一個實體或另一個實體。 其他所有步驟均相同。 我已經突出顯示了每個代碼段中代碼都不同的那一行。

    ProductCsvReader.java

    public class ProductCsvReader {Set<Product> getAll(File file) throws IOException {Set<Product> returnSet = new HashSet<>();try (BufferedReader reader = new BufferedReader(new FileReader(file))){String line = reader.readLine();while (line != null && !line.trim().equals("")) {String[] tokens = line.split("\\s*,\\s*");Product product = new Product(Integer.parseInt(tokens[0]), tokens[1],new BigDecimal(tokens[2]));returnSet.add(product);line = reader.readLine();}}return returnSet;} }

    CustomerCsvReader.java

    public class CustomerCsvReader {Set<Customer> getAll(File file) throws IOException {Set<Customer> returnSet = new HashSet<>();try (BufferedReader reader = new BufferedReader(new FileReader(file))){String line = reader.readLine();while (line != null && !line.trim().equals("")) {String[] tokens = line.split("\\s*,\\s*");Customer customer = new Customer(Integer.parseInt(tokens[0]), tokens[1],tokens[2], tokens[3]);returnSet.add(customer);line = reader.readLine();}}return returnSet;} }

    在此示例中,只有兩個實體,但是實際系統(tǒng)中可能有數(shù)十個實體,因此有很多容易出錯的重復代碼。 對于DAO,您可能會發(fā)現(xiàn)類似的情況,其中每個DAO的選擇,插入,更新和刪除操作將執(zhí)行相同的操作,僅適用于不同的實體和表。 讓我們開始重構這個麻煩的代碼。 根據(jù)GoF設計模式書第一部分中的一種設計原則,我們應該“封裝變化的概念”。 在ProductCsvReader和CustomerCsvReader之間,突出顯示的代碼有所不同。 因此,我們的目標是將變化的內容封裝到單獨的類中,同時將保持不變的內容移動到單個類中。 讓我們首先開始編輯一個類,即ProductCsvReader。 我們使用提取方法將行提取到自己的方法中:

    提取方法后的ProductCsvReader.java

    public class ProductCsvReader {Set<Product> getAll(File file) throws IOException {Set<Product> returnSet = new HashSet<>();try (BufferedReader reader = new BufferedReader(new FileReader(file))){String line = reader.readLine();while (line != null && !line.trim().equals("")) {String[] tokens = line.split("\\s*,\\s*");Product product = unmarshall(tokens);returnSet.add(product);line = reader.readLine();}}return returnSet;}Product unmarshall(String[] tokens) {Product product = new Product(Integer.parseInt(tokens[0]), tokens[1], new BigDecimal(tokens[2]));return product;} }

    既然我們已經分離出了哪些變化與哪些保持不變,我們將創(chuàng)建一個父類,該父類將保存兩個類保持相同的代碼。 我們將此父類稱為AbstractCsvReader。 讓我們使其抽象,因為沒有理由單獨實例化該類。 然后,我們將使用Pull Up Method重構將保持不變的方法移到該父類。

    AbstractCsvReader.java

    abstract class AbstractCsvReader {Set<Product> getAll(File file) throws IOException {Set<Product> returnSet = new HashSet<>();try (BufferedReader reader = new BufferedReader(new FileReader(file))){String line = reader.readLine();while (line != null && !line.trim().equals("")) {String[] tokens = line.split("\\s*,\\s*");Product product = unmarshall(tokens);returnSet.add(product);line = reader.readLine();}}return returnSet;} }

    上拉方法后的ProductCsvReader.java

    public class ProductCsvReader extends AbstractCsvReader {Product unmarshall(String[] tokens) {Product product = new Product(Integer.parseInt(tokens[0]), tokens[1], new BigDecimal(tokens[2]));return product;} }

    此類無法編譯,因為它調用了在子類中找到的“ unmarshall”方法,因此我們需要創(chuàng)建一個稱為unmarshall的抽象方法。

    使用抽象解組方法的AbstractCsvReader.java

    abstract class AbstractCsvReader {Set<Product> getAll(File file) throws IOException {Set<Product> returnSet = new HashSet<>();try (BufferedReader reader = new BufferedReader(new FileReader(file))){String line = reader.readLine();while (line != null && !line.trim().equals("")) {String[] tokens = line.split("\\s*,\\s*");Product product = unmarshall(tokens);returnSet.add(product);line = reader.readLine();}}return returnSet;}abstract Product unmarshall(String[] tokens); }

    現(xiàn)在,AbstractCsvReader將成為ProductCsvReader的出色父級,而不是CustomerCsvReader的父級。 如果從AbstractCsvReader擴展,CustomerCsvReader將不會編譯。 為了解決這個問題,我們使用泛型。

    具有泛型的AbstractCsvReader.java

    abstract class AbstractCsvReader<T> {Set<T> getAll(File file) throws IOException {Set<T> returnSet = new HashSet<>();try (BufferedReader reader = new BufferedReader(new FileReader(file))){String line = reader.readLine();while (line != null && !line.trim().equals("")) {String[] tokens = line.split("\\s*,\\s*");T element = unmarshall(tokens);returnSet.add(product);line = reader.readLine();}}return returnSet;}abstract T unmarshall(String[] tokens); }

    帶有泛型的ProductCsvReader.java

    public class ProductCsvReader extends AbstractCsvReader<Product> {@OverrideProduct unmarshall(String[] tokens) {Product product = new Product(Integer.parseInt(tokens[0]), tokens[1], new BigDecimal(tokens[2]));return product;} }

    CustomerCsvReader.java與泛型

    public class CustomerCsvReader extends AbstractCsvReader<Customer> {@OverrideCustomer unmarshall(String[] tokens) {Customer customer = new Customer(Integer.parseInt(tokens[0]), tokens[1], tokens[2], tokens[3]);return customer;} }

    就是這樣! 沒有更多重復的代碼! 父類中的方法是“模板”,其中包含保持不變的代碼。 更改的內容保留為抽象方法,這些方法在子類中實現(xiàn)。 請記住,重構時,應該始終進行自動化的單元測試,以確保不破壞代碼。 我將JUnit用于我的。 您可以在Github存儲庫中找到我在此處發(fā)布的代碼以及其他一些“設計模式”示例。 在開始之前,我想簡單介紹一下模板方法的缺點。 模板方法依賴于繼承,而繼承則存在脆弱的基類問題 。 簡而言之,脆弱的基類問題描述了基類的更改如何被子類繼承,并經常導致不良后果。 實際上,在GoF本書開始時發(fā)現(xiàn)的基本設計原則之一就是“偏向于繼承而不是繼承”,許多其他設計模式都說明了如何避免代碼重復,復雜度或其他容易出錯的代碼,而減少了依賴關于繼承。 請給我反饋,以便我可以繼續(xù)完善我的文章。

    翻譯自: https://www.javacodegeeks.com/2014/07/template-method-pattern-example-using-java-generics.html

    總結

    以上是生活随笔為你收集整理的使用Java泛型的模板方法模式示例的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。