Effective Java 第二版笔记之考虑使用静态工厂方法代替构造器

栏目: 后端 · 发布时间: 6年前

内容简介:Effective Java 第二版笔记之考虑使用静态工厂方法代替构造器

创建对象最直接的想法就是通过 new 调用构造器,其实大多数情况下应当通过自己写一个静态公有方法,返回类的实例,比如下面这个方法:

  public static Boolean valueOf(boolean b) {
       return b ? Boolean.TRUE : Boolean.FALSE;
}

和直接使用构造器相比,使用静态工厂方法具有以下优点:

  • 静态工厂方法可以根据用途自己定义名称(不必与类相同),可读性更强
  • 静态工厂方法可能不用在每次调用时都创建新对象
  • 静态工厂方法可以返回声明类型的子类型的实例

下面分别阐述这三个优点。

静态工厂方法可以根据用途自己定义名称

构造器的方法名只能使用类名,如果有多个构造器,只能通过参数类型甚至顺序来区分,这样可读性非常差,而且不容易记,调用的时候很容易出错。

public class TantanitReader {
    private int age;
    private String loginName;
    private String realName;
    private String career;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public String getCareer() {
        return career;
    }

    public void setCareer(String career) {
        this.career = career;
    }
}

比如在上面的例子中,类 TantanitReader 表示我的官方博客 tantanit.com 的读者信息,其中 age 表示年龄,loginName 表示登录名,realName 表示真实姓名,career 表示职业,除了 age 是 int 类型之外,其它几个都是字符串类型。

假设现在需要根据年龄和登录名,创建一个读者,使用构造器的话,代码如下:

public TantanitReader(int age, String loginName) {
    this.age = age;
    this.loginName = loginName;
}

假设又有一个场景,需要根据年龄(int 类型)和真实姓名(String 类型)创建读者,如果使用构造器的话,参数类型和上一个构造器相同,要解决这个问题呢?机智如你,一定想到通过对调参数顺序这个取巧(而不优雅)的方法,来规避这个问题。

public TantanitReader(String realName, int age) {
    this.realName = realName;
    this.age = age;
}

如果一个类要通过构造器创建读者,就需要根据这两个构造器的参数顺序记住各自的用法,是不是很容易记错啊。就算记住了也要查文档或者看看 TantanitReader 这个类的源文件,再确认一遍吧。

好了,又来了一个场景,需要根据年龄(int 类型)和职业创建读者,如果使用构造器的话,相信聪明如你,也是没有办法了。

所以,应当使用静态工厂方法来代替构造器。下面的代码很好地解决了这个问题:

public static TantanitReader getByAgeAndLoginName(int age,String loginName){
    TantanitReader tantanitReader=new TantanitReader();
    tantanitReader.setAge(age);
    tantanitReader.setLoginName(loginName);
    return tantanitReader;
}

public static TantanitReader getByAgeAndRealName(int age,String realName){
    TantanitReader tantanitReader=new TantanitReader();
    tantanitReader.setAge(age);
    tantanitReader.setRealName(realName);
    return tantanitReader;
}

public static TantanitReader getByAgeAndCareer(int age,String career){
    TantanitReader tantanitReader=new TantanitReader();
    tantanitReader.setAge(age);
    tantanitReader.setCareer(career);
    return tantanitReader;
}

三个方法使用不同的名称,并且在名称中暗示了参数的顺序,这样,在调用的时候,就不容易出错,也不用再查看文档或构造函数的源码了。

静态工厂方法可能不用在每次调用时都创建新对象

使用静态工厂方法,在有些使用场景下,可以重复使用一个提前生成的对象,或者从缓存中获取一个对象,而不用创建一个新的对象。文章开头的例子中的 Boolean.valueOf(boolean)方法,调用时就不用创建新的对象。这样节省了内存开销,也提高了性能。同时,和每次都 new 一个新的对象,都是不同的对象相比,在这种重复使用的场景中,每次返回的对象都是严格意义相同的对象,可以做到对象级别的控制。这种控制对单例和不可实例化的使用场景很有用,并且可以放心的使用 == 代替 equals 方法,以提高性能。比如枚举类就使用了这样的技术。

静态工厂方法可以返回声明类型的子类型的实例

构造函数,只能返回该类的实例,不能返回该类的子类的实例,静态工厂方法不受这个限制,因此可以很好地使用 Java 语言的多态性。在方法声明返回值类型为父类型,甚至接口类型,而返回子类型或接口的某个类型的具体实现。这样,将来想返回其它子类型或接口的其它实现时,只要直接修改方法体,不用改方法声明,不影响调用方的使用。

谈谈 IT的文章均为原创或翻译(翻译会注明外文来源),转载请以链接形式标明本文地址: http://tantanit.com/effectiv-java-static-method-replace-constructor/

Effective Java 第二版笔记之考虑使用静态工厂方法代替构造器

欢迎关注官方微信公众号获取最新原创文章


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python编程实战

Python编程实战

[美] Mark Summerfield / 爱飞翔 / 机械工业出版社 / 2014-8 / 69.00元

《python编程实战:运用设计模式、并发和程序库创建高质量程序》由python开发者社区知名技术专家mark summerfield亲笔撰写,全球资深python专家doug hellmann作序鼎力推荐,是python领域最有影响力的著作之一。书中通过大量实用的范例代码和三个完整的案例研究,全面而系统地讲解了如何运用设计模式来规划代码结构,如何通过并发与cython等技术提升代码执行速度,以及......一起来看看 《Python编程实战》 这本书的介绍吧!

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具