[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'

[Java] Design Pattern:Code Shape - manage your code shape的更多相关文章

  1. java design pattern - adapter pattern

    场景 适配器模式 总结 参考资料 场景 在编程中我们经常会遇到驴头不对马嘴的情况,比如以前是继承A的接口的对象,现在外部调用的时候需要该对象已B接口的形式来调用 ,这个时候我们可以让对象同时集成A和B ...

  2. Java Design Pattern(Factory,Singleton,Prototype,Proxy)

    一.Factory 设计模式: the most common pattern,create a new object ,eg. A a=new A();工厂模式的好处:工厂模式可以做到把创建对象单独 ...

  3. JAVA DESIGN PATTERN

    工厂模式(factory) 简单工厂模式的概念 就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建.简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承 ...

  4. Java并发编程:Concurrent锁机制解析

    Java并发编程:Concurrent锁机制解析 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: # ...

  5. java设计模式大全 Design pattern samples in Java(最经典最全的资料)

    java设计模式大全 Design pattern samples in Java(最经典最全的资料) 2015年06月19日 13:10:58 阅读数:11100 Design pattern sa ...

  6. Scalaz(10)- Monad:就是一种函数式编程模式-a design pattern

    Monad typeclass不是一种类型,而是一种程序设计模式(design pattern),是泛函编程中最重要的编程概念,因而很多行内人把FP又称为Monadic Programming.这其中 ...

  7. design principle:java 回调与委派/委托机制

    博客 design principle:模拟 android Button 控件点击事件 主要说了一下模拟 android 的 Listener 模式,其实这就是一种委派与回调机制的体现. 委派,也可 ...

  8. Template Method Design Pattern in Java

    Template Method is a behavioral design pattern and it’s used to create a method stub and deferring s ...

  9. State Design Pattern

    注: 转载自 https://www.geeksforgeeks.org/state-design-pattern/  [以便查阅,非原创] State Design Pattern State pa ...

随机推荐

  1. PHP中抽象方法、抽象类和接口的用法

    在类中,没有方法体的方法就是抽象方法. abstract 可见性 function 方法名称(参数1,.....);      // 如果没有显示地指定可见性,则默认为public 如: public ...

  2. MySQL-5.6版本GTID的主从复制

    mysql GTID Replication 一.GTID的概述: 1.全局事物标识:global transaction identifieds. 2.GTID事物是全局唯一性的,且一个事务对应一个 ...

  3. 「GXOI / GZOI2019」旧词

    题目 确定这不是思博题 看起来很神仙,本来以为是\([LNOI2014]LCA\)的加强版,结果发现一个点的贡献是\(s_i\times (deep_i^k-(deep_i-1)^k)\),\(s_i ...

  4. PHP学习笔记一:谁动了你的mail(),PHP?

    PHP编写邮件发送的函数时候,会出现一个很奇怪的问题,那就是: Warning: mail(): Failed to connect to mailserver at "localhost& ...

  5. 构建 CDN 分发网络架构

    cdn基本架构: CDN的基本目的:1.通过本地缓存实现网站的访问速度的提升 CDN的关键点:CNAME在域名解析:split智能分发,引流到最近缓存节点

  6. 让你的QT显示一个窗口吧

    项目文件 01_QtTest.pro #------------------------------------------------- # # Project created by QtCreat ...

  7. 在centos6.5下用nginx无法连接zabbix与mysql的解决办法

    一般情况下默认的webserver是apache.zabbix也不例外,官方文档全都是推荐用apache. 如果执意用nginx来做webserver的话,php引导需要再安装一个php-fpm.而且 ...

  8. 函数的返回值是void

    #include <stdio.h> void sub(int x,int y,int z){ z=y-x; } void main() { int a=1,b=2,c=3; sub(10 ...

  9. 【转】CSDN离线网页html文件自动跳转

    问题: 最近使用OneNote2016剪辑csdn的文章时,发现一些公式/文本框不能被正确识别,所以离线保存网页的html文件. 但是每次打开html文件,都会自动跳转的CSDN主页,即使断网,也会自 ...

  10. Word里面怎么取消全文每个标题前面都有的这个点

    Word里标题前面的那个点,如图1所示看起来觉得很不舒服,该怎么把它取消呢?(本测试环境是Win 10 64位系统,Microsoft Office家庭和学生版 2016) 图1 选中所有标题,如图2 ...