[Java] 设计模式:代码形状 - lambda表达式的一个应用
[Java] 设计模式: Code Shape - 管理你的代码结构
Code Shape 设计模式
这里介绍一个设计模式: Code Shape。
如果你没有听说的,没问题。这个名字是我刚刚起的。
作用
在应用软件开发中,我们经常会采用多层架构。在每一层中,不同的方法往往呈现相同的代码结构。
这里我们称之为:Code Shape。
比如:在数据访问层,写方法都可能有下面这些代码:
- 获取数据库连接
- 创建一个事务
- 写入数据
- 提交事务
- 如果发生异常,回滚事务
除此之外,有时,架构师希望增加一些架构功能,比如:
- 统一处理权限认证
- 统一处理异常
- 记录日志
- 对性能做profiling
- 记录方法的参数值
这时,设计模式 Code Shape 通过使用Lambda表达式,实现了上面的需求。
提供了一种灵活的方式,管理每层方法的代码结构。
代码示例
本位提供了一个代码示例,完成下面功能:
- 在调用一个业务逻辑之前,写一个日志。
- 在调用一个业务逻辑之后,写一个日志。
- 在调用一个业务逻辑时发生异常,写一个日志。
- 记录方法的参数值。
- 如果有,记录返回值。
预备知识
关于 Java 8 Lambda 表达式,请参考 这里。
Java 提供了 java.util.function.Consumer
和 java.util.function.Function
,方便我们去使用Lambda表达式。
Consumer
被用于没有返回值的方法,Function
被用于有返回值的方法。
不幸的是,这两个接口只支持一个输入参数。
如果需要,我们需要写一些接口,来支持多个输入参数。
这是,提供了支持两个输入参数的例子:
- 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'
[Java] 设计模式:代码形状 - lambda表达式的一个应用的更多相关文章
- Java基础教程(23)--lambda表达式
一.初识lambda表达式 1.定义 lambda表达式是一个可传递的代码块,或者更确切地说,可以把lambda表达式理解为简洁地表示可传递的匿名方法的一种方式.它没有名称,但它有参数列表.函数主 ...
- Java核心技术-接口、lambda表达式与内部类
本章将主要介绍: 接口技术:主要用来描述类具有什么功能,而并不给出每个功能的具体实现.一个类可以实现一个或多个接口. lambda表达式:这是一种表示可以在将来的某个时间点执行的代码块的简洁方法. 内 ...
- Upgrading to Java 8——第一章 Lambda表达式
第一章 Lambda表达式 Lamada 表达式是Java SE 8中最重要的新特性,长期以来被认为是在Java中缺失的特性,它的出现使整个java 语言变得完整.至少到目前,在这节中你将学习到什么是 ...
- Java函数式编程和lambda表达式
为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于 ...
- Java 8 中的 Lambda 表达式
Lambda 表达式是 Java 8 最受欢迎的功能.人们将函数式编程的概念引入了 Java 这门完全面向对象的命令式编程语言. 关于函数式编程是如何运作的,这个话题超出了本文的范围,不过我们会提炼出 ...
- Java 8新增的Lambda表达式
一. 表达式入门 Lambda表达式支持将代码块作为方法参数,lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例,相当于一个匿名的方法. 1.1 La ...
- Java基础教程:Lambda表达式
Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...
- Java 8 (2) 使用Lambda表达式
什么是Lambda? 可以把Lambda表达式理解为 简洁的表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表.函数主体.返回类型,可能还有一个可以抛出的异常列表. 使用Lambda可以让你更 ...
- java函数式编程之lambda表达式
作为比较老牌的面向对象的编程语言java,在对函数式编程的支持上一直不温不火. 认为面向对象式编程就应该纯粹的面向对象,于是经常看到这样的写法:如果你想写一个方法,那么就必须把它放到一个类里面,然后n ...
随机推荐
- VMware网络配置
NAT模式 首先保证虚拟机网卡和主机对接,虚拟机网络连接要和主机在同一网段 1. 控制面板\网络和 Internet\网络连接中配置VMnet8 2. 编辑虚拟机网络配置 此处子网ip需要和Vnet8 ...
- Python Tornado初学笔记之表单与模板(一)
Tornado中的表单和HTML5中的表单具有相同的用途,同样是用于内容的填写.只是不同的是Tornado中的表单需要传入到后台,然后通过后台进行对模板填充. 模板:是一个允许嵌入Python代码片段 ...
- “认证发布”和“获取展示”,如何在 SharePoint 中正确使用 RSS Feed。
在我们进行的日常工作中,是由一部分信息需要 Share 给其他人或者组织的.SharePoint 虽然支持在某个 Site Collection 中互通信息,但是跨 Site Collection 的 ...
- 实现一个网易云音乐的 BottomSheetDialog
作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...
- python/MySQL练习题(二)
python/MySQL练习题(二) 查询各科成绩前三名的记录:(不考虑成绩并列情况) select score.sid,score.course_id,score.num,T.first_num,T ...
- baidu地图:实现多点连线渲染
<script type="text/javascript"> var points = [ {"Lng":125.17787645967861,& ...
- Hive:insert into table 与 insert overwrite table 区别
创建测试表,来测试看看测试结果: create table test(name string,pwd string,createdate string)row format delimited fie ...
- POJ-1995 Raising Modulo Numbers---快速幂模板
题目链接: https://vjudge.net/problem/POJ-1995 题目大意: 求一堆ab的和模上m 思路: 直接上模板 #include<iostream> #inclu ...
- 一个web程序员的年终总结
2017年年终总结(就是一个程序员的瞎叨叨): 从来到中科院到现在,很开心可以在这留下来.毕竟对于我来说,这里符合我对自己毕业后前两年的规划.我是一个很慢的人,特别是对于我想做好的事情,我会非常认真仔 ...
- 在脚本中使用source命令不生效
问题描述 1. 一次写自动化安装脚本,要安装java,需要将JAVA_HOME写到/etc/profile中,然后使用source命令,但是发现profile文件中确实有JAVA_HOME,使用 ...