用Lambda實現模板模式
Java 8 Lambda表示式的簡潔性為經典的GoF設計模式提供了新的視角。透過利用函數語言程式設計,我們可以透過更少的耦合和儀式獲得相同的好處 - 模板方法就是一個很好的例子。
經典的GoF模板方法實現
模板方法設計模式是Gang of Four描述的23種設計模式之一 - 利用它可以輕鬆地符合Open-Closed和Hollywood原則。
簡而言之,它有助於定義某個演算法的骨架(演算法不變數),使用者可以填充空白 - 這是透過覆蓋定義骨架實現的抽象類所暴露的抽象方法來實現的。
更實際,想象一些場景,比如記錄某些操作的執行時間,在事務中執行程式碼......或者經典的JUnit工作流,我們只負責以前/後/測試方法的形式填充空白 - 這些是場景圖案閃耀的地方。
讓我們看一個相當簡單的例子,包括用執行時間記錄來包圍我們的程式碼。
經過專業訓練的GoF設計模式從業者將使用抽象類來實現這個想法:
abstract class AbstractTimeLoggingMethod { abstract void run(); public void runWithTimeLogging() { var before = LocalTime.now(); run(); var after = LocalTime.now(); System.out.printf( "Execution took: %d ms%n", Duration.between(before, after).toMillis()); } } |
然後,如果我們想用記錄邏輯包裝我們的程式碼片段,我們只需要擴充套件類,然後使用public方法:
public static void main(String[] args) { var fetchAndLog = new AbstractTimeLoggingMethod() { @Override void run() { findById(42); } }; fetchAndLog.runWithTimeLogging(); // Execution took: 1005 ms } |
然而,由於它依賴於繼承,這種方法非常具有侵入性 - 它將類緊密地耦合在一起並且用過多的樣板程式碼。
用函式簡化模板方法
我們可以在一個接受函式介面的方法中實現,而不是透過使用抽象類來定義骨架:
final class TemplateMethodUtil { private TemplateMethodUtil() { } static void runWithExecutionTimeLogging(Runnable action) { var before = LocalTime.now(); action.run(); var after = LocalTime.now(); System.out.printf( "Execution took: %d ms%n", Duration.between(before, after).toMillis()); } } |
現在,只要我們想要傳入函式方法:
TemplateMethodUtil.runWithExecutionTimeLogging(() -> findById(42)) |
想要編排多個呼叫?
static void orchestrate(Runnable step1, Runnable step2) { System.out.println("starting..."); step1.run(); step2.run(); System.out.println("ending..."); } |
呼叫客戶端:
TemplateMethodUtil.orchestrate( () -> System.out.println("a"), () -> System.out.println("b")); starting... a b ending... |
GoF書中充滿了規範性的想法,但仍然值得重新審視它們,因為新的方法可以實現更好的實現。
程式碼片段可以在GitHub上找到。
相關文章
- 模板方法模式(c++實現)模式C++
- 使用lambda實現裝飾者模式 - Voxxed模式
- Go 實現常用設計模式(七)模板方法模式Go設計模式
- lambda實現遞迴遞迴
- 用Lambda重構責任模式鏈模式
- 設計模式實戰-模板方法模式設計模式
- <七>lambda表示式實現原理
- 設計模式 | 模板方法模式及典型應用設計模式
- 使用C# (.NET Core) 實現模板方法模式 (Template Method Pattern)C#模式
- 設計模式、用Delphi實現---->Builder模式 (轉)設計模式UI
- Java 8中Lambda表示式預設方法的模板方法模式,你夠了解麼?Java模式
- 模板模式模式
- C++設計模式:Singleton的模板實現之一 (轉)C++設計模式
- 用Python實現設計模式——單例模式Python設計模式單例
- 用Python實現設計模式——工廠模式Python設計模式
- 設計模式、用Delphi實現---->Singleton 模式 (轉)設計模式
- 用SpringBoot實現策略模式Spring Boot模式
- JavaScript模板引擎的應用場景及實現原理JavaScript
- 設計模式-模板模式設計模式
- 設計模式——模板模式設計模式
- 通過模板實現POI
- 用鍵值儲存實現MVCC模式MVC模式
- Blazor Web 應用如何實現Auto模式BlazorWeb模式
- 模板方法模式模式
- 用Python實現設計模式——建造者模式和原型模式Python設計模式原型
- 《JavaScript設計模式與開發實踐》模式篇(8)—— 模板方法模式JavaScript設計模式
- 只用lambda演算實現FizzBuzz遊戲(Python版)遊戲Python
- 策略模式與模板方法模式模式
- 設計模式-模板方法模式設計模式
- 設計模式 ——— 模板方法模式設計模式
- 命令模式 & 策略模式 & 模板方法模式
- 實現物件的複用——享元模式(五)物件模式
- 實現物件的複用——享元模式(四)物件模式
- 實現物件的複用——享元模式(三)物件模式
- 實現物件的複用——享元模式(二)物件模式
- 實現物件的複用——享元模式(一)物件模式
- Java Tip: 用Reflection實現Visitor模式 (轉)Java模式
- 用SERVICE LOCATOR 模式實現命名訪問 (轉)模式