今天我们分享另外一个创建型的模式:建造者模式。在讲解建造者模式之前,我们首先来看一个需求示例。
案例简单说明
假设有一个简单需求,需要对不同业务场景的日志进行统一规范化格式打印或者上送至Kafka。
下面给出一个简单规范化日志类,包含场景、服务名、方法名、耗时、code和错误信息。
构造函数
针对多种场景的不同标准需要,可能包含多个构造函数的使用,以满足不同场景下日志输出。如:
静态方法代替构造函数
当构造函数有多个的时候,比如有2个类型都是3个String类型的参数,但是不同字段,这时候构造函数只能有一个。
此时,我们可能会使用静态方法代替构造函数来做,只要取一个能区分场景的方法名字即可。
比如:
public static RegularLogInfo getBasicLogInfo(String serviceName, String methoodName, long costTime) { //DO SOMETHING } ... ...
静态方法虽然解决了一定的问题,但是如果随着需要打印的内容增多。无论构造函数还是静态方法创建对象都变得麻烦。
比如;
增加traceId和spanId,又如增加集群信息(dc、clusterName、appName)等等。
面对属性字段较多、对象形态多样性的场景,今天的主角【建造者模式】闪亮登场。
意图
建造者模式是一种创建型的模式,其意图是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
基本结构
Note:建造者模式是体现局部和整体关系的,产品是一步步构建,最终形成的一定是一个整体。
就比如顾客去餐厅购买一份儿童餐,跟收银员说要汉堡、饮料、甜甜圈有额外的玩具等,最终顾客得到是包含所有的儿童餐,是一个整体。
日志类增加属性
创建一个Builder
编写Builder类的一个简单方法就是使用如下几个步骤:
编写Builder类
将RegularLogInfo的属性都放到Builder类中,如:
增加一个静态的newBuilder()方法, 用于返回Builder对象
以每个属性的名字,命名方法,赋值后返回本身也就是this
最后,增加一个build()方法,赋值后返回具体对象即可,本例为RegularLogInfo。
调用示例
3个步骤即可
如:
这样,使用Builder模式创建一个规范化日志对象就完成了。只要按照具体场景进行赋值即可,非常灵活。
其它写法
当然,除了上述的写法外,也可以将Builder写到具体类里面。比如,使用Lombok的@Builder注解,其就是通过修改抽象语法树,在类内部增加一个静态内部类Builder来做的。如下图所示:
有兴趣的读者可以深入去分析一下。
上述场景,我们为RegularLogInfo类写了一个RegularLogInfoBuilder。如果类似场景较多,我们是不是需要编写多个Builder来完成。
那么问题来了,有什么通用的方法吗,写一个到处能用的那种?
答案是肯定的。其实,使用Lombok的@Builder注解,就是一种通用的做法。
另外,我们可以借助JDK1.8后Supplier来实现一个通用的Builder构建器写法。有兴趣的读者可以参考之前的博文:一个通用的 Builder构建器写法
至此,建造者模式的由来和通用写法思考就完成了。
最后,我们再来思考一下?
如果Builder()创建后,赋值需要按照一定的顺序,也就是要按照一定的步骤,我们该如何处理呢?比如,先赋值环境信息env,再赋值trace信息,最后赋值业务信息biz。如:
RegularLogInfo regularLogInfo =
RegularLogInfoBuilder.newBuilder()
.env(envInfo)
.trace(traceInfo)
.biz(bizInfo)
.build();
在下一篇博文中,我们一起来完成这样的操作。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。