zoukankan      html  css  js  c++  java
  • [Java] Design Pattern:Code Shape

    [Java] Design Pattern:Code Shape - manage your code shape

    Code Shape Design Pattern

    Here I will introduce a design pattern: Code Shape。
    It's fine that you never heard that, I just created it.

    Usage

    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:

    • Get the database connection.
    • Begin a transaction.
    • Write database.
    • Commit the transaction.
    • When there is an exception, rollback the transaction.

    Beside, some times, architects hope to add some infrastructure functions, e.g.

    • Unified processing authority authentication.
    • Unified handling exceptions.
    • Logging.
    • Profiling for performance.
    • Logging method parameters.

    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.

    Code Demonstrate

    This article presents a code demonstrate to implement following features:

    • Before calling a method, write a log
    • Log method parameters
    • After calling the method, write a log
    • If applicable, log the return value
    • When there is an exception, log the exception

    Prerequisites

    About Java 8 Lambda Expressions, please see here.

    Java provides java.util.function.Consumer and java.util.function.Function, to benefit us a convenience way to use lambda expressions.

    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:

    • 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 indicates this is a function interface, only one method is defined inside.

    Main class code

    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.

    Code:

    • 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 Design Pattern Code

    • 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;
        }
    }
    
    

    Explanation 1:using Consumer

    OK. All code is presented, let's explain them.

    • Business Rule Code
      As this business rule method does not return any thing, so I use CodeShapePattern.consumerShape.
      There are 2 input parameters.: business rule logical and the method's parameter values.
    	/*
    	 * 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 Design Pattern Code - Consumer
      We can see it, the consumerShape is a static variable that implements unified functions.
      This consumerShape uses a nested Consumer.
      The Consumer inside is the business rule logical., In business rule methods, you can write any code what you want.
      BTW, the input parameter is useless, we may define a ConsumerZero interface to simplify the code.
        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 {
    		}
    	};
    
    

    Explanation 2: Using Function

    • Business Rule Layer method
      As this business rule layer method has return, we use CodeShapePattern.<R>getFunctionShape() inside.
      getFunctionShape() is a generic method, the generic type is the return type of the business rule method.
      There are 2 parameters:
      The first: business rule logical, with return.
      The second: parameters of the business rule method, for internal use.
    	/*
    	 * 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 Design Pattern - Function
      Different as the consumerShape, getFunctionShape is a static generic method that implements unified functions.
      This getFunctionShape uses a nested Function.
      The Function inside is the business rule logical., In business rule methods, you can write any code what you want.
      BTW, the input parameter is useless, we may define a FunctionZero interface to simplify the code.
        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;
    	}
    
    

    Output result

    
    ========
    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'
    
  • 相关阅读:
    让Python支持中文注释
    【转】python入门指引
    【转】布同:如何循序渐进学习Python语言
    在nagios中监控windows主机系统地址的状态
    大神
    music
    20·15-01-21
    2015-01-20
    2015-01-19
    2015-01-18
  • 原文地址:https://www.cnblogs.com/steven-yang/p/8954782.html
Copyright © 2011-2022 走看看