程序员这行干的久了,总会染上一些恶习,我就染上一个让人深恶痛绝,自己却津津乐道的习惯,还不想改的那种,它可以叫做强迫症,也可以叫做洁癖。那就是我不允许我的IDEA出现一点点警告,什么黄色背景,绿色波浪线,统统不允许,按下F2键必须是这样

当然,说这些也没有意义,因为并没有说如何去做,所以今天我准备开一个新的系列——如何写出高效清爽的Java代码,这意味着这整个系列的所有案例都会十分严谨且苛刻。如果有小伙伴说:这一丁点性能有什么嘛,无所谓啦。我:不,一丁点也不允许!

高效:开发高效,性能高效

今天是第一篇——使用静态工厂方法代替构造器

名字的重要性

一千个人眼里有一千个哈姆雷特,一千个项目里有个一千个通用响应对象,比如ApiResponseResponseResultBaseResult 等等,它们的结构一般都像这样

  1. public class BaseResult<T> implements Serializable {
  2. private static final long serialVersionUID = -9127050844792378533L;
  3. /**
  4. * 状态码
  5. */
  6. private int code;
  7. /**
  8. * 消息
  9. */
  10. private String message;
  11. /**
  12. * 需要返回的数据对象
  13. */
  14. private T data;
  15. public BaseResult() {
  16. }
  17. public BaseResult(int code, String message) {
  18. this(code, message, null);
  19. }
  20. public BaseResult(int code, String message, T data) {
  21. this.code = code;
  22. this.message = message;
  23. this.data = data;
  24. }
  25. // 省略get/set方法
  26. }

一般我们会定义code为0,或者200什么的表示正确响应,其他的为错误响应。

使用的示例如下:

  1. public BaseResult<Order> getOrder(){
  2. Order order = new Order();
  3. return new BaseResult<>(0, "成功", order);
  4. }

这样子使用咋一看好像没什么问题,那是因为我先告诉大家code=0是正确,再给出相应的示例,如果小伙伴直接看示例多半会懵住:0是指什么?因为0在这里是个魔法值。或者说,正确的响应码发生变更,项目经理说,code=0太不好看了,改成200!这个时候...完蛋。

这时候我们可以多加一个专门用来描述code的类,如:

  1. public interface ResultCode {
  2. /**
  3. * 正确响应码
  4. */
  5. int SUCCESS = 0;
  6. /**
  7. * 错误响应码
  8. */
  9. int FAILURE = -1;
  10. }

使用方式就发生了变更:

  1. public BaseResult<Order> getOrder(){
  2. Order order = new Order();
  3. return new BaseResult<>(ResultCode.SUCCESS, "成功", order);
  4. }

现在,我们消除了魔法值,而且不管项目经理说把code改成啥都行,我们只改ResultCode.SUCCESS的值就行。

项目经理:code改成字符类型!

但是!如果每个接口的返回值都这样写,就会发现,整个项目都充斥这new BaseResult<>(ResultCode.SUCCESS, "成功", value)这样的语句,这一行代码只有value不一样,其他全都一模一样,啊,这丑陋的代码。

于是,我们继续改进,增加两个静态方法:

  1. public static <T> BaseResult<T> success(T data){
  2. return new BaseResult<>(ResultCode.SUCCESS, ResultCode.SUCCESS_MESSAGE, data);
  3. }
  4. public static BaseResult<Void> failure(){
  5. return new BaseResult<>(ResultCode.FAILURE, ResultCode.FAILURE_MESSAGE);
  6. }

在ResultCode类中增加两个常量:

  1. String SUCCESS_MESSAGE = "成功";
  2. String FAILURE_MESSAGE = "失败";

如果每次new BaseResult<>(ResultCode.SUCCESS, "成功", order)的话, 成功这个字符串则会随着每次new出BaseResult而创建出一个字符串对象。

改进后的使用方式:

  1. public BaseResult<Order> getOrder(){
  2. Order order = new Order();
  3. return BaseResult.success(order);
  4. }

使用者再也不需要关心code是啥,cool~

项目经理:给我把code改.... 开发:啪(巴掌声)

不必每次构建都创建对象

有时候调用的接口不需要返回参数,只需要响应一个正确或者失败即可,此时我们就需要一个无参的success方法:

  1. public static BaseResult<Void> success(){
  2. return new BaseResult<>(ResultCode.SUCCESS, ResultCode.SUCCESS_MESSAGE);
  3. }

使用:

  1. public BaseResult<Void> createOrder(){
  2. return BaseResult.success();
  3. }

不知道小伙伴有没有发现一个问题,这个无参的success方法每次返回的对象都是相同的,但是每次都创建了一个新的对象出来!啊,糟糕的代码!

改进:

  1. public static final BaseResult<Void> SUCCESS = new BaseResult<>(ResultCode.SUCCESS, ResultCode.SUCCESS_MESSAGE);
  2. public static final BaseResult<Void> FAILURE = new BaseResult<>(ResultCode.FAILURE, ResultCode.FAILURE_MESSAGE);
  3. public static BaseResult<Void> success(){
  4. return SUCCESS;
  5. }
  6. public static BaseResult<Void> failure(){
  7. return FAILURE;
  8. }

这里顺手把failure方法也改进一下

现在,每次调用无参success`方法时都使用一个静态对象,不再发生重复创建!爽!

注意,需要data数据的BaseResult不要这样做,否则会出现线程安全问题

闭环

有时候接口不仅会与页面交互,服务与服务之间也会产生交互,这时候如果我们想要判断其他接口的响应情况,会怎么做呢?

  1. public void callOtherServer(){
  2. BaseResult<Void> result = createOrder();
  3. if(result.getCode() == ResultCode.SUCCESS){
  4. // 正确
  5. }
  6. }

现阶段我们只能这样做,啊,这糟糕的代码又出现了!

改进:

  1. public boolean isSuccess(){
  2. return this.code == ResultCode.SUCCESS;
  3. }
  4. public boolean isFailure(){
  5. return this.code != ResultCode.SUCCESS;
  6. }

改进后的使用方式:

  1. public void callOtherServer(){
  2. BaseResult<Void> result = createOrder();
  3. if(result.isSuccess()){
  4. // 正确
  5. }
  6. }

优雅的代码!

小结

本篇介绍了关于使用静态工厂方法代替构造器的美好事情

第一:使用一个好名字对构造逻辑进行封装

第二:有时候并不需要每次重复的创建对象

第三:建立一个逻辑闭环

学会了的小伙伴看看自己的项目有没有改进的空间吧~

原创地址:https://zijiancode.cn/archives/usestaticmethod

看完之后想必有所收获吧~ 想要了解更多精彩内容,欢迎关注公众号:程序员阿鉴,阿鉴在公众号欢迎你的到来~

高效JAVA之用静态工厂方法代替构造器的更多相关文章

  1. 改善JAVA代码01:考虑静态工厂方法代替构造器

    前言 系列文章:[传送门]   每次开始新的一本书,我都会很开心.新书新心情. 正文 静态工厂方法代替构造器 说起这个,好多可以念叨的.做了一年多的项目,慢慢也有感触. 说起构造器 大家很明白,构造器 ...

  2. Java - 用静态工厂方法代替构造器

    Effective Item - 考虑用静态工厂方法代替构造器我们有两种常见的方法获得一个类的实例: 公有的构造器 提供静态工厂方法(static factory method) 相对公有的构造器,静 ...

  3. Effective Java 读书笔记(一):使用静态工厂方法代替构造器

    这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...

  4. effective java 3th item1:考虑静态工厂方法代替构造器

    传统的方式获取一个类的实例,是通过提供一个 public 构造器.这里有技巧,每一个程序员应该记住.一个类可以对外提供一个 public 的 静态工厂方法 ,该方法只是一个朴素的静态方法,不需要有太多 ...

  5. 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器

    类可以提供一个静态方法,返回类的一个静态实例,如Boolean包装类的一个获取实例的静态方法 public static Boolean valueOf(boolean b) { return (b ...

  6. Effective java读书札记第一条之 考虑用静态工厂方法取代构造器

    对于类而言,为了让client获取它自身的一个实例,最经常使用的方法就是提供一个共同拥有的构造器. 另一种放你发,也应该子每一个程序猿的工具箱中占有一席之地.类能够提供一个共同拥有的静态 工厂方法.它 ...

  7. 【读书笔记 - Effective Java】01. 考虑用静态工厂方法代替构造器

    获取类的实例有两种方法: 1. 提供一个公有的构造器(最常用). 2. 提供一个公有的静态工厂方法(static factory method). // 静态工厂方法示例 public static ...

  8. 静态工厂方法VS构造器

    我之前已经介绍过关于构建者模式(Builder Pattern)的一些内容,它是一种很有用的模式用于实例化包含几个属性(可选的)的类,带来的好处是更容易读.写及维护客户端代码.今天,我将继续介绍对象创 ...

  9. Tips1:考虑用静态工厂方法代替构造器

    用静态工厂方法来代替构造器为外界提供对象 描述: 静态工厂方法代替构造器来给外界提供对象,创建对象依然是由构造器来完成的 创建对象和提供对象: 创建对象的方式: 构造器 提供对象来哦方式: 构造器 类 ...

随机推荐

  1. VisualEffectGraph概述

    Visual Effect Graph 由来: Visual Effect Graph 是2018.3 以后版本,出的新的粒子特效技术.它是用显卡渲染特效,区别于传统的Patical system 的 ...

  2. 乘风破浪,.Net Core遇见MAUI(.NET Multi-platform App UI),进击现代化跨设备应用框架

    什么是MAUI https://github.com/dotnet/maui .NET Multi-platform App UI (MAUI) 的前身是Xamarin.Forms(适用于Androi ...

  3. Zabbix5.0微信报警

    3.1.注测企业微信: 3.2.企业微信注册成功后进入后台管理: 3.3.添加一个部门,并记住部门id: #我这里添加的子部门ID为2 3.4.添加一个用户到上面创建的部门里面(这里采取直接将管理员添 ...

  4. 5、linux分区

    5.1.分区的选择: 5.2.文件系统: ext2.ext3.ext4 5.3.分区的类型(MBR): 硬盘的使用前需要分区-格式化(创建文件系统)-存放数据: 一块硬盘: 主分区(必须有,最多4个) ...

  5. 12、Linux磁盘设备基础知识(2)

    12.4.计算磁盘容量: 磁盘的大小=盘面大小*磁头数 盘面的大小=磁道大小*磁道数 磁道大小=512字节*扇区数 磁盘的大小=512字节*扇区数*磁道数*磁头数 磁盘的大小=柱面大小*柱面数 柱面大 ...

  6. 38、mysql数据库(pymysql及事务)

    38.1.python之pymysql模块: 1.说明: pymsql是Python中操作MySQL的模块,其使用方法和py2的MySQLdb几乎相同. 2.模块安装: pip install pym ...

  7. js 对json数据进行检索 插件 linq.js

    有时界面需要很多数据.但是多次访问服务器效率很低,所以需要检索json数据,最好是像sql查询语句那种 linq.js 插件 LINQ,语言集成查询(Language Integrated Query ...

  8. python之字典(dict)基础篇

    字典:dict 特点: 1>,可变容器模型,且可存储任意类型对象,字符串,列表,元组,集合均可: 2>,以key-value形式存在,每个键值 用冒号 : 分割,每个键值对之间用逗号 , ...

  9. 浅读tomcat架构设计之Pipeline-Valve管道(4)

    tomcat Container容器处理请求是使用Pipeline-Valve管道来处理的,后续写的tomcat内存马,和他紧密结合 Pipeline-Valve是责任链模式,责任链模式是指在一个请求 ...

  10. AcWing 829. 模拟队列

    实现一个队列,队列初始为空,支持四种操作: (1) "push x" – 向队尾插入一个数x: (2) "pop" – 从队头弹出一个数: (3) " ...