1. 考虑使用静态工厂替代构造方法

优点:
  • 见名知意:相对于构造方法,工厂方法取名更加灵活,生成的客户端代码更易阅读。
  • 不需要每次调用都创建一个新对象:针对不可变类或创建对象代价比较高昂的类,可预先构建实例或构建时缓存实例
  • 可返回其返回类型的任何子类型的对象(类库更易拓展)
  • 可根据输入参数的不同而不同(可读性降低)
  • 在编写包含该方法的类时,返回的对象的类不需要存在(使用依赖注入更佳)

    缺点:
  • 相对于通过构造方法创建对象,静态工厂方法不易被查找到,需要完善的文档加以说明

    2. 当构造方法参数过多时使用Builder模式

    示例:
  1. @AllArgsConstructor
  2. @Builder
  3. @Data
  4. public class User{
  5. private int age;
  6. private float weight;
  7. private String name;
  8. private float height;
  9. }
  10. @Test
  11. public void createUserTest(){
  12. // 通过构造方法创建对象
  13. User white = new User(16,71.2f,"white",1.82f);
  14. // 通过建造者模式创建对象
  15. User colde = User.builder()
  16. .age(16)
  17. .height(1.82f)
  18. .name("colde")
  19. .weight(71.2f)
  20. .build();
  21. }

应用场景:

当构造对象所属参数较多是,直接通过构造对象或者工厂方法无法知晓参数明确的含义,不易阅读,而且极易出错。如上列中直接通过构造函数new User(16,71.2f,"white",1.82f)创建对象,无法清晰得出(16,71.2f,”white”,1.82f)对应的含义,可能出现升高71.2体重1.82的情况。通过示例中Builder模式能够很好的解决此类问题,并且搭配Lombok,只需加上@Builder注解,无需再去书写板式代码就能简单的实现Builder模式

3. 使用私有构造方法或枚举类实现单例

实现单例最佳实践:单一元素枚举类

获取数据库连接伪代码

  1. public enum DataSourceEnum{
  2. INSTANCE;
  3. @Getter
  4. private DataSource dataSource;
  5. DataSourceEnum(){
  6. dataSource = new DataSource();
  7. }
  8. }

Java规范字规定,每个枚举类型及其定义的枚举变量在JVM中都是唯一的,从而保障单例对象的安全性

4. 使用私有构造方法执行非实例化

避免工具类被实例化

  1. public class XXXXUtil{
  2. private XXXXUtil(){
  3. throw new AssertionError();
  4. }
  5. }

5. 依赖注入优于硬编码

  • 提高了代码的灵活性和可测试性
  • 降低了模块与模块之间的耦合度

    6. 避免创建不必要的对象

  • 复用字符串常量池,不要通过new的方式去创建字符串对象

  • 复用创建代价高昂的对象
  • 优先使用基本类型,避免无意识的自动装箱

    7. 消除过期的对象引用

    内存泄漏的两个诱因:
  • 过期引用:解决办法,把过期的对象引用置为空

  • 缓存:使用WeakHashMap来表示缓存

8. 避免使用Finalizer和Cleaner机制

  • 两种机制都是不可预知的,不能保证他们能够及时执行