博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第1条:考虑用静态工厂方法代替构造器
阅读量:6407 次
发布时间:2019-06-23

本文共 3220 字,大约阅读时间需要 10 分钟。

为了获得一个类的实例,有两种办法1.类提供一个公有的构造器 2.类提供一个公有的静态工厂方法。

 

静态工厂方法的优势:

1.有名称。

慎重地选择方法名称能突出多个构造器的区别,例如使用BigInteger(int, int, Random)构造器,返回的BigInteger可能为素数,如果用

BigInteger.probalePrime(int, Random)静态工厂方法,显得更为清楚。

 

2.不必在每次调用的时候都创建一个新的对象。

Boolean类的代码中有public static final Boolean TRUE = new Boolean(true)  这样一个TURE常量,它在类加载的时候就把这个常量初始化,在valueOf方法中每次返回

的都是这个常量。

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

 

3.可以返回原返回类型的任何子类型的对象。(多态)

 java.util.EnumSet没有公有构造器,只有静态工厂方法,返回两种实现类之一,具体取决于底层枚举类型的大小,如果元素有64个或更少,返回一个RegualrEumSet实例,用单个long支持,如果多于64个,则返回JumboEnumSet实例,用long数组进行支持。

public static 
> EnumSet
noneOf(Class
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);} //RegularEnumSet用单个long支持private long elements = 0L; //JumboEnumSet用long数组支持private long elements[];

RegualrEumSet和JumboEnumSet这两个实现类对客户来说不可见,客户只关心的是它是某个EnumSet的某个子类,如果RegularEnumSet不能给小的枚举类型提供性能优势,就有可能从未来的发行版中将它删除,不会对客户造成任何影响,如果在未来的发行版中要添加第三第四个甚至更多EnumSet实现,对客户也没有任何影响。

 

一个服务提供者的框架:

//服务接口,由服务提供者实现public interface Service {    //服务方法...}//服务提供者接口,由服务提供者实现public interface Provider {    Service newService();}//一个服务注册和获得服务的不可实例化类public class Services {    private Services() {};        //服务提供者名-服务提供者的映射    private static final Map
providers = new ConcurrentHashMap
(); public static final String DEFAULT_PROVIDER_NAME = "
"; //服务提供者注册API,系统用来注册实现 public static void registerDefaultProvider(Provider p) { registerProvider(DEFAULT_PROVIDER_NAME, p); } public static void registerProvider(String name, Provider p) { providers.put(name, p); } //服务访问API,客户用来获取服务实例 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(); } }

结合JDBC的数据库连接服务理解:Connection是服务接口,DriverManager.registerDriver是提供者注册API,DriverManager.getConnection是服务访问API,Driver就是服务提供者接口。

这样的实现使得Services类(在JDBC中,即是DriverManager类)的代码几乎不需要修改了(就算是修改也不会把框架改了,只会优化,对外的接口是不会变的),现在来了一个新的数据库厂商,该厂商只需要提供实现了Provider接口的服务提供者,实现Service接口的服务,就可以了,不会对客户造成任何影响,因为客户根本不知道多了一个新的数据库。

 

4.在创建参数化类型实例的时候,使代码变得更加简洁。

Map
> m = new HashMap
>()

调用参数化类型时,需要两次提供类型参数<String, List<String>>

假如HashMap提供了这样一个静态工厂:

public static 
HashMap
newInstance() { return new HashMap
();}

就能使用

Map
> m = HashMap.newInstance();

代替原来的冗长代码。

 

静态工厂方法的主要缺点:

1.类的构造器如果是私有的,就不能被子类化。

2.它们与其他静态方法实际上没有任何区别。

就像上面提到的EnumSet类,它没有提供公有的构造器,所以无法这样实例化EnumSet s = new EnumSet(),在Eclipse会提示你这个类不没通过构造器实例化,除此之外没有任何有用的消息了,它不会告诉你使用noneof、allof这样的静态工厂方法来实例化该对象。

转载于:https://www.cnblogs.com/13jhzeng/p/5601942.html

你可能感兴趣的文章
Git 仓库大扫除
查看>>
设计模式-单例模式
查看>>
es6基础0x014:WeakMap
查看>>
九种 “姿势” 让你彻底解决跨域问题
查看>>
php中mysqli 处理查询结果集总结
查看>>
你不知道的JavaScript运算符
查看>>
小程序开发注意事项
查看>>
ECMAScript7规范中的instanceof操作符
查看>>
Hadoop HDFS原理分析
查看>>
【webpack4】基本配置和入门api
查看>>
Mac使用ssh公钥登录Linux
查看>>
【366天】跃迁之路——程序员高效学习方法论探索系列(实验阶段124-2018.02.06)...
查看>>
POJ3070-Fibonacci(矩阵快速幂)
查看>>
[vue插件]基于vue2.x的电商图片放大镜插件
查看>>
标准的组件结构
查看>>
vue——一个页面实现音乐播放器
查看>>
SVG 扬帆起航
查看>>
NET Core-学习笔记(二)
查看>>
职业生涯上的点点滴滴
查看>>
Linux下添加新硬盘,分区及挂载
查看>>