高效Java01:考虑使用静态工厂方法代替构造方法

Java中的每一个类被创建,大部分场景中客户端都需要获取它自身的一个实例然后进行使用,我们最常用的是为它提供一个公有的构造方法,除此之外还可以使用静态工厂方法返回它的一个实例。相较于构造方法,静态工厂方法拥有以下好处:

  • 它们拥有不同的自定义名称
  • 调用它时无需重复创建新对象
  • 它们可以返回类型的任何子类型的对象
  • 创建参数化类型实例的时候,它们使代码更加简洁(JDK1.7以后就不算优势了)

静态工厂方法优势一:它们拥有不同的自定义名称

如果构造方法中的参数不能准确的表述会返回什么对象,那么具有适当名称的静态工厂方法则更容易使用,产生的客户端代码也更易于理解。

例如有如下构造方法:

Person(String, int, String)

返回的Person即可能为男人,也可能为女人,当然我们可以创建多个构造方法来解决这个问题,但随着构造方法的增多,使用者很难确定使用哪个构造方法,特别是在参考文档却是的情况下。

如果使用静态工厂方法Person.male创建男人对象,使用Person.female创建女人对象则更准确。

静态工厂方法优势二:调用时无需重复创建新对象

调用构造方法每次都会创建一个新的实例对象,而有些场景中我们需要控制实例数或者基于性能考虑不能总是重新创建对象,这个时候,可以使用预先初始化实例对象,将其缓存起来,用到的时候直接返回即可。如JDK中的Boolean.valueOf(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);
    }
}

其中TRUEFALSE均为预先初始化的实例,静态工厂方法仅进行直接返回已缓存的对象。

静态工厂方法优势三:它们可以返回类型的任何子类型的对象

我们先看一段示例代码:

public interface Service {
}
public interface Provider {
    Service newService();
}
public class Services {
    private Services() {}

    private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();
    public static final String DEFAULT_PROVIDER_NAME = "<def>";

    public static void registerDefaultProvider(Provider p) {
        registerProvider(DEFAULT_PROVIDER_NAME, p);
    }

    public static void registerProvider(String name, Provider p) {
        providers.put(name, p);
    }

    public static Service newInstance() {
        return newInstance(DEFAULT_PROVIDER_NAME);
    }

    public static Service newInstance(String name) {
        Provider p = providers.get(name);
        if (p == null)
            throw new IllegalArgumentException("No provider registered with name: " + name);
        return p.newService();
    }
}

上面的代码中,接口Provider会有多个实现类,而每个实现类中的newService()方法均会返回接口Service实现类的具体实例化对象,比如在业务场景busA下,需要使用名称为busAProviderProvider提供具体服务实例,我们仅需调用Services.newInstance("busAProvider")即可获得对应的服务对象实例,而对于外部调用者,只需要调用Services.newInstance("String)即可,调用newInstance()等同于Services.newInstance("<def>")

静态工厂方法优势四:创建泛型实例的时候,它们使代码更加简洁(JDK1.7以后就不算优势了)

在JDK1.7之前我们必须这样实例化对象:

Map<String,List<Map<String,Objects>>> map = new HashMap<String,List<Map<String,Objects>>>();

类型参数越来越长,我们实例化对象时也必须指明,假设HashMap提供了一个静态工厂方法:

public static <K, V> HashMap<K, V> newInstance(){
    return new HashMap<K, V>();
}

我们仅需这样调用:

Map<String,List<Map<String,Objects>> map = HashMap.newInstance();

使用静态工厂方法后,编译器会自动帮我们找到对应的类型,这个功能叫做类型推导,JDK1.7新增了一个钻石操作符<>实现了该功能,在1.7中我们可以使用它更简单的完成泛型对象的实例化:

Map<String,List<Map<String,Objects>>> map = new HashMap<>();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值