Here I will introduce a design pattern: Code Shape。
It's fine that you never heard that, I just created it.html
In the enterprise application development, in most cases, we adopt multiple layers architectures.
Methods in each layer tend to present the same code structure. Here we name it as code shape.
For example, in the database access layer, writing methods would have following code:java
Beside, some times, architects hope to add some infrastructure functions, e.g.express
So, the design pattern code shape implements the above requirements by using Java lambda expressions
Provide a flexible way to manage every method shape in a layer.oracle
This article presents a code demonstrate to implement following features:app
About Java 8 Lambda Expressions, please see here.less
Java provides java.util.function.Consumer
and java.util.function.Function
, to benefit us a convenience way to use lambda expressions.ide
Consumer
can be used by non-return methods, and Function
can be used by methods which have return.
Unfortunately, they only support one argument.
Therefore, if need, we have to write interfaces to support multiple arguments.
Here are samples to support tow input arguments:flex
@FunctionalInterface public interface ConsumerTwo<T, T2> { public void accept(T t, T2 t2); }
@FunctionalInterface public interface FunctionTwo<T, T2, R> { public R apply(T t, T2 t2); }
Annotation FunctionalInterface
indicates this is a function interface, only one method is defined inside.ui
The main class calls 3 samples:
The first sample: it is a method without return.
The second sample: it is a method without return, but always throw an exception.
The third sample: it is a method with return.this
Code:
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"); } }
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)); } }
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; } }
OK. All code is presented, let's explain them.
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)); }
Consumer
.Consumer
inside is the business rule logical., In business rule methods, you can write any code what you want.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)); } };
Less code version:
public static ConsumerTwo<Consumer<Object>, List<Object>> consumerShape = (body, params) -> { try { body.accept(null); } catch (Exception e) { throw e; } finally { } };
CodeShapePattern.<R>getFunctionShape()
inside./* * 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)); }
Function
.Function
inside is the business rule logical., In business rule methods, you can write any code what you want.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; }
Less code version:
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'