(写篇文章不容易啊,在公司看完书,写完笔记,然后复制回来再发布。。。)
静态工厂创建对象的时候有三大好处
1. 静态工厂方法有名称,能够更加容易的使用(明确功能),代码的可读性更强。
//构造函数
BigInteger b = BigInteger(int bitLength, int certainty, Random rnd)
//静态工厂
BigInteger b = BigInteger.probablePrime(int bitLength, Random rnd)
上面两种方式,使用静态工厂更加能够表明意思
2. 静态工厂方法不必在每次调用它们的时候都创建一个新的对象
这对于不可变类来说,可以使用已经构造好的实例对象,可重复使用对象。也可以构造单例模式的类。
例如:Boolean flag = Boolean.valueOf(boolean b);
每次使用的就是Boolean类中创建的TRUE或FALSE两个对象
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static void main(String[] agrs) {
Boolean f = Boolean.TRUE;
Boolean k = Boolean.TRUE;
System.out.println(f == k); //true
System.out.println(f.equals(k)); //true
Boolean a = new Boolean(true);
Boolean b = new Boolean(true);
System.out.println(a==b); //false
System.out.println(a.equals(b)); //true
}
静态工厂方法能够为重复调用返回相同的对象,这样有助于类总能严格控制在某个时刻哪些实例应该存在,这种类被称为实例受控的类
静态工厂方法创建的实例是当f==k时会有f.equals(k)为true,那么就可以使用==替代equals,这样可以提升效率。例如:枚举类型。
3. 静态工厂方法可以返回任何原类型的子类型的对象!
这个优势在我看来就是,通过静态工厂方法,获取一个接口时,不需要关心内部的实现机制是怎么样的。比如,我需要通过一个静态工厂方法获取一个List接口,那么静态工厂方法在内部实现上就可以非常灵活,比如new ArrayList();或者new LinkedList()返回。
另外,可以通过静态工厂方法指定需要返回什么类型的对象,在接收的时候最好用接口接收(像上面那样使用List接收,这是好习惯)。Collections就是一个静态工厂,里面提供了很多静态方法。书里面举的EnumSet的例子也可以。
书中另外一个例子,服务提供者框架讲的就很好
服务提供者框架定义:多个服务提供者提供一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。
对应到JDBC的例子就是,很多个服务提供者提供了连接数据库的服务(比如MySQL服务提供者实现了连接MySQL数据库的服务,Oracle服务提供者实现了连接Oracle数据库的服务。总的来说,它们都是连接数据库的服务),各个服务实现之间互不关联(解耦)。
服务提供者的三个组件:
服务接口,服务提供者需要实现的接口(Connection)
提供者注册API,系统用来注册实现,让客户端访问它们的(这里的客户端可以是实现服务的一方,把提供的服务注册进去)(DriverManager.registerDriver())
服务访问API,客户端用来获取服务实例的(DriverManager.getConnection(),可用适配器模式)
TODO:链接:下次写一篇JDBC实现原理
4. 在创建参数化类型实例的时候,使得代码更加简洁
这点就没什么好说的,书中举的Map<String, List<String>> map = new HashMap<String, List<String>>();这个例子在JDK5中是成立的,最好提供一个静态工厂方法,然后通过类型推断的方式来做。但是在JDK8中已经优化了这一点了,会自动类型推断的。
两个缺点:
1、如果类没有包含公有的或者保护的构造函数就不能被子类化,这一点刚好可以让我们多用组合,少用继承
2、静态工厂方法的静态方法与其他静态方法没有区别,这其实不算什么大的缺点吧,书中也提供了一些常用的静态方法名,其实把注释写好就OK了。
读Effective Java - 001条 考虑用静态工厂方法代替构造器
最新推荐文章于 2024-10-27 00:55:08 发布