[Java] 設計模式: Code Shape - 管理你的代碼結構

[Java] 設計模式: Code Shape - 管理你的代碼結構

Code Shape 設計模式

這裏介紹一個設計模式: Code Shape。
若是你沒有據說的,沒問題。這個名字是我剛剛起的。html

做用

在應用軟件開發中,咱們常常會採用多層架構。在每一層中,不一樣的方法每每呈現相同的代碼結構。
這裏咱們稱之爲:Code Shape
好比:在數據訪問層,寫方法均可能有下面這些代碼:java

  • 獲取數據庫鏈接
  • 建立一個事務
  • 寫入數據
  • 提交事務
  • 若是發生異常,回滾事務

除此以外,有時,架構師但願增長一些架構功能,好比:數據庫

  • 統一處理權限認證
  • 統一處理異常
  • 記錄日誌
  • 對性能作profiling
  • 記錄方法的參數值

這時,設計模式 Code Shape 經過使用Lambda表達式,實現了上面的需求。
提供了一種靈活的方式,管理每層方法的代碼結構。express

代碼示例

本位提供了一個代碼示例,完成下面功能:設計模式

  • 在調用一個業務邏輯以前,寫一個日誌。
  • 在調用一個業務邏輯以後,寫一個日誌。
  • 在調用一個業務邏輯時發生異常,寫一個日誌。
  • 記錄方法的參數值。
  • 若是有,記錄返回值。

預備知識

關於 Java 8 Lambda 表達式,請參考 這裏架構

Java 提供了 java.util.function.Consumerjava.util.function.Function,方便咱們去使用Lambda表達式。oracle

Consumer 被用於沒有返回值的方法,Function 被用於有返回值的方法。
不幸的是,這兩個接口只支持一個輸入參數。
若是須要,咱們須要寫一些接口,來支持多個輸入參數。
這是,提供了支持兩個輸入參數的例子:app

  • ConsumerTwo
@FunctionalInterface
public interface ConsumerTwo<T, T2> {
    public void accept(T t, T2 t2);
}
  • FunctionTwo
@FunctionalInterface
public interface FunctionTwo<T, T2, R> {
    public R apply(T t, T2 t2);
}

Annotation FunctionalInterface 標示這個接口是一個function interface,內部只定義了一個方法。性能

代碼:Main類

這個Main類調用了三個例子:
第一個例子:調用了一個沒有返回值的業務邏輯方法。
第二個例子:調用了一個沒有返回值的業務邏輯方法,實際上,會拋出異常。
第三個例子:調用了一個有返回值的業務邏輯方法。
代碼:設計

  • Main.java
public class Main {
    public static void main(String[] args) {
        
        pattern.CodeShapeSample br = new pattern.CodeShapeSample();

        // call business rule one
        br.businessRuleOne("Jack", "is man");

        // call business rule two, will get an exception
        try {
            br.businessRuleTwoThrowException("Tom", "is woman");
        }
        catch (Exception e) {}

        // call business rule three which has a return.
        String value = br.businessRuleThree("Mary", "is woman");
    }
}

代碼:Code Shape 設計模式

  • CodeShapeSample
package pattern;

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

public class CodeShapeSample {
    
    /*
     * This is a consumer sample
     */
    public void businessRuleOne(final String name, final String value) {
        
        CodeShapePattern.consumerShape.accept((o) -> {
            // here is business rule logical
            System.out.println("here is business rule logical 1.");
        }, Arrays.asList(name, value));
    }
    
    /*
     * This is a consumer with exception sample
     */
    public void businessRuleTwoThrowException(final String name, final String value) {
        
        CodeShapePattern.consumerShape.accept((o) -> {
            // here is business rule logical
            System.out.println("here is business rule logical 2.");
            throw new RuntimeException("failure!");
        }, Arrays.asList(name, value));
    }
    
    /*
     * This is a function sample
     */
    public String businessRuleThree(final String name, final String value) {
        
        return CodeShapePattern.<String>getFunctionShape().apply((o) -> {
            // here is business rule logical
            System.out.println("here is business rule logical 3.");
            return name + " " + value;
        }, Arrays.asList(name, value));
    }
}
  • CodeShapePattern
package pattern;

import java.text.MessageFormat;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

public class CodeShapePattern {

    public static ConsumerTwo<Consumer<Object>, List<Object>> consumerShape = (body, params) -> 
    {
        StackTraceElement caller = new Exception().getStackTrace()[2];
        String method = caller.getClassName() + "#" + caller.getMethodName();
        try {
            System.out.println("");
            System.out.println("========");
            System.out.println(MessageFormat.format("start method ''{0}''", method));
            if (params != null) {
                for(Object param : params) {
                    System.out.println(MessageFormat.format("parameter : ''{0}''", param.toString()));
                }
            }
            
            System.out.println("---- start body ----");
            body.accept(null);
            System.out.println("---- end body ----");
        }
        catch (Exception e) {
            System.out.println(MessageFormat.format("error method ''{0}'': {1}", method, e.getMessage()));
            throw e;
        }
        finally {
            System.out.println(MessageFormat.format("end method ''{0}''", method));
        }
    };
    
    public static <R> FunctionTwo<Function<Object, R>, List<Object>, R> getFunctionShape() {
        FunctionTwo<Function<Object, R>, List<Object>, R> function = (body, params) -> 
        {
            R ret = null;
            StackTraceElement caller = new Exception().getStackTrace()[2];
            String method = caller.getClassName() + "#" + caller.getMethodName();
            try {
                System.out.println("");
                System.out.println("========");
                System.out.println(MessageFormat.format("start method ''{0}''", method));
                if (params != null) {
                    for(Object param : params) {
                        System.out.println(MessageFormat.format("parameter : ''{0}''", param.toString()));
                    }
                }
                
                System.out.println("---- start body ----");
                ret = body.apply(null);
                System.out.println("---- end body ----");
            }
            catch (Exception e) {
                System.out.println(MessageFormat.format("error method ''{0}'': {1}", method, e.getMessage()));
                throw e;
            }
            finally {
                System.out.println(MessageFormat.format("end method ''{0}'', return ''{1}''", method, ret.toString()));
            }
            return ret;
        };
        
        return function;
    }
}

代碼說明 1:使用 Consumer

好了,這裏已經提供了全部的代碼。如今,讓咱們逐一解釋。

  • 代碼:業務邏輯
    因爲下面這個業務規則方法沒有返回值,因此使用CodeShapePattern.consumerShape
    這裏有兩個輸入參數:
    第一個是:業務規則邏輯。
    第二個是:方法的參數值,用於內部使用。
/*
     * This is a consumer sample
     */
    public void businessRuleOne(final String name, final String value) {
        
        CodeShapePattern.consumerShape.accept((o) -> {
            // here is business rule logical
            System.out.println("here is business rule logical 1.");
        }, Arrays.asList(name, value));
    }
  • 代碼:Code Shape 設計模式 - Consumer
    咱們能夠看到,consumerShape 是一個靜態變量,實現了統一的功能。
    這個 consumerShape 使用了一個嵌套的 Consumer
    內部的 Consumer 是業務規則邏輯, 在業務規則邏輯,你想怎麼寫,就怎麼寫。
    順便說一句:內部的 Consumer的輸入參數是沒用的,咱們能夠定義一個 ConsumerZero 接口來簡化代碼。
public static ConsumerTwo<Consumer<Object>, List<Object>> consumerShape = (body, params) -> 
    {
        StackTraceElement caller = new Exception().getStackTrace()[2];
        String method = caller.getClassName() + "#" + caller.getMethodName();
        try {
            System.out.println("");
            System.out.println("========");
            System.out.println(MessageFormat.format("start method ''{0}''", method));
            if (params != null) {
                for(Object param : params) {
                    System.out.println(MessageFormat.format("parameter : ''{0}''", param.toString()));
                }
            }
            
            System.out.println("---- start body ----");
            body.accept(null);
            System.out.println("---- end body ----");
        }
        catch (Exception e) {
            System.out.println(MessageFormat.format("error method ''{0}'': {1}", method, e.getMessage()));
            throw e;
        }
        finally {
            System.out.println(MessageFormat.format("end method ''{0}''", method));
        }
    };

簡化版:

public static ConsumerTwo<Consumer<Object>, List<Object>> consumerShape = (body, params) -> 
    {
        try {
            body.accept(null);
        }
        catch (Exception e) {
            throw e;
        }
        finally {
        }
    };

代碼說明 2:使用 Function

好了,這裏已經提供了全部的代碼。如今,讓咱們逐一解釋。

  • 代碼:業務邏輯
    因爲下面這個業務規則方法有返回值,因此使用CodeShapePattern.<R>getFunctionShape()
    getFunctionShape()是一個泛型方法,這個泛型是業務邏輯方法的返回類型。
    這裏有兩個輸入參數:
    第一個是:業務規則邏輯,有返回值。
    第二個是:方法的參數值,用於內部使用。
/*
     * This is a function sample
     */
    public String businessRuleThree(final String name, final String value) {
        
        return CodeShapePattern.<String>getFunctionShape().apply((o) -> {
            // here is business rule logical
            System.out.println("here is business rule logical 3.");
            return name + " " + value;
        }, Arrays.asList(name, value));
    }
  • 代碼:Code Shape 設計模式 - Function
    不一樣於consumerShape, getFunctionShape 是一個靜態泛型方法,實現了統一的功能。
    這個 getFunctionShape 使用了一個嵌套的 Function
    內部的 Function 是業務規則邏輯, 在業務規則邏輯,你想怎麼寫,就怎麼寫。
    順便說一句:內部的 Function的輸入參數是沒用的,咱們能夠定義一個 FunctionZero 接口來簡化代碼。
public static <R> FunctionTwo<Function<Object, R>, List<Object>, R> getFunctionShape() {
        FunctionTwo<Function<Object, R>, List<Object>, R> function = (body, params) -> 
        {
            R ret = null;
            StackTraceElement caller = new Exception().getStackTrace()[2];
            String method = caller.getClassName() + "#" + caller.getMethodName();
            try {
                System.out.println("");
                System.out.println("========");
                System.out.println(MessageFormat.format("start method ''{0}''", method));
                if (params != null) {
                    for(Object param : params) {
                        System.out.println(MessageFormat.format("parameter : ''{0}''", param.toString()));
                    }
                }
                
                System.out.println("---- start body ----");
                ret = body.apply(null);
                System.out.println("---- end body ----");
            }
            catch (Exception e) {
                System.out.println(MessageFormat.format("error method ''{0}'': {1}", method, e.getMessage()));
                throw e;
            }
            finally {
                System.out.println(MessageFormat.format("end method ''{0}'', return ''{1}''", method, ret.toString()));
            }
            return ret;
        };
        
        return function;
    }

簡化版:

public static <R> FunctionTwo<Function<Object, R>, List<Object>, R> getFunctionShape() {
        FunctionTwo<Function<Object, R>, List<Object>, R> function = (body, params) -> 
        {
            R ret = null;

            try {
                ret = body.apply(null);
            }
            catch (Exception e) {
                throw e;
            }
            finally {
            }
            return ret;
        };
        
        return function;
    }

輸出結果

========
start method 'pattern.CodeShapeSample#businessRuleOne'
parameter : 'Jack'
parameter : 'is man'
---- start body ----
here is business rule logical 1.
---- end body ----
end method 'pattern.CodeShapeSample#businessRuleOne'

========
start method 'pattern.CodeShapeSample#businessRuleTwoThrowException'
parameter : 'Tom'
parameter : 'is woman'
---- start body ----
here is business rule logical 2.
error method 'pattern.CodeShapeSample#businessRuleTwoThrowException': failure!
end method 'pattern.CodeShapeSample#businessRuleTwoThrowException'

======== start method 'pattern.CodeShapeSample#businessRuleThree' parameter : 'Mary' parameter : 'is woman' ---- start body ---- here is business rule logical 3. ---- end body ---- end method 'pattern.CodeShapeSample#businessRuleThree', return 'Mary is woman' ```

相關文章
相關標籤/搜索