1、考虑使用静态工厂方法替代构造方法 (Effective- java 学习笔记)

静态工厂方法提供了一种替代构造方法的方式,具备命名优势、无需新对象、返回子类型等优点,常用于服务提供者框架。尽管它们可能导致类无法被子类化且不易发现,但通常情况下,静态工厂方法更可取。了解它们的优缺点有助于选择合适的方法创建对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于一个类,要获取它的一个实例,通常的做法是提供一个公用的构造函数,然而还有另一种方法,我们称之为静态工厂方法,实质上也就是一个简单的静态方法,它返回一个类的实例。其实,静态工厂方法获取对象实例,我们并不陌生,我们来看看API中的一个实例:

首先注意 ,静态工厂方法与设计模式中的工厂方法模式是不同的。
下面是一个Boolean的中的实例

public final class Boolean implements java.io.Serializable, Comparable<Boolean>{
    
    public static final Boolean TRUE = new Boolean(true);

    public static final Boolean FALSE = new Boolean(false);
    
    public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }
}

类可以为其客户端提供静态工厂方法,而不是公共构造方法。但是既有优点,也有缺点。

第一个优点是,不像构造方法,它们是有名字的。 比如返回一个可能为素数的BigInteger的构造方法BigInteger(int, int, Random),可以被更好的命名为BigInteger.probablePrime的静态工厂方法。提高可读性。

第二个优点是,与构造方法不同,不需要每次都创建一个新对象,这个看看上方Boolean的代码示例就会明白

第三个优点是, 与构造方法不同,它们可以返回任意类型的任何子类型的对象

第四个优点是,返回的对象的类可以根据输入参数的不同而不同

EnumSet 类(条目 36)没有公共构造方法,只有静态工厂。

/**
     * Creates an empty enum set with the specified element type.
     *
     * @param <E> The class of the elements in the set
     * @param elementType the class object of the element type for this enum
     *     set
     * @return An empty enum set of the specified type.
     * @throws NullPointerException if <tt>elementType</tt> is null
     */
    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        Enum<?>[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);
    }

第五个优点是,在编写包含该方法的类时,返回的对象的类不需要存在
这种灵活的静态工厂方法
构成了服务提供者框架的基础,比如 Java 数据库连接 API(JDBC)。服务提供者框架是提供者实现服务的系统,并且系
统使得实现对客户端可用,从而将客户端从实现中分离出来。

只提供静态工厂方法的主要限制是,没有公共或受保护方法的类不能被子类化

第二个缺点是,程序员很难找到它们,哈哈,就问你怕不怕

以下是一些静态工厂方法的常用名称:

  • from——A 类型转换方法,它接受单个参数并返回此类型的相应实例,例如:Date d = Date.from(instant);

  • of——一个聚合方法,接受多个参数并返回该类型的实例,并把他们合并在一起,例如:Set faceCards = EnumSet.of(JACK, QUEEN, KING);

  • valueOf——from 和 to 更为详细的替代 方式,例如:BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE); instance 或 getinstance——返回一个由其参数 (如果有的话) 描述的实例,但不能说它具有相同的值,例如:
    StackWalker luke = StackWalker.getInstance(options);

  • create 或 newInstance——与 instance 或 getInstance 类似,除了该方法保证每个调用返回一个新的实例,例如:
    Object newArray = Array.newInstance(classObject, arrayLen);

  • getType——与 getInstance 类似,但是如果在工厂方法中不同的类中使用。Type 是工厂方法返回的对象类型,例
    如:FileStore fs = Files.getFileStore(path);

  • newType——与 newInstance 类似,但是如果在工厂方法中不同的类中使用。Type 是工厂方法返回的对象类型,
    例如:BuweredReader br = Files.newBuweredReader(path);

  • type—— getType 和 newType 简洁的替代方式,例如:List litany = Collections.list(legacyLitany);

总之,静态工厂方法和公共构造方法都有它们的用途,并且了解它们的相对优点是值得的。通常,静态工厂更可
取,因此避免在没有考虑静态工厂的情况下提供公共构造方法。

ps:如果有微信读书的书友,可以来微信读书群传送门找组织。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值