一、用静态工厂方法代替构造器

类通过共有的构造方法可以提供很大的优点:
1、构造方法可一有不同的名字,我们可以通过名字区分构造什么样子的对象,而构造器名字相同,当参数列表的数目相同 顺序不同时 很大的可能会用错构造方法。

2、可以每次调用他们的时候都使用相同的对象(单例模式),可以对一个对象重复的利用,而每次调用构造方法都会新建一个对象。当程序需要创建相同的对象或者创建对象的代价很高时,使用静态工厂是一个很好的选择。

3、使用静态工厂可以返回原返回类型的任意子类型。在静态工程方法中可以根据不同的条件返回不用的对象。

服务提供者框架:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从实现中解耦出来 减少服务提供者之间的关联。

4、使用泛型 创建参数化类型实例的时候 可以让代码更简洁。
编译器可以通过静态工厂来找到类型参数。

静态工厂方法

以Java中自带的Boolean类(基本类型boolean的包装类)为例,它的静态工厂方法为:

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

我们应该考虑用该方法替代构造器来获得一个Boolean的实例。

//使用构造器
Boolean b1 = new Boolean(true);
//使用静态工厂方法
Boolean b2 = Boolean.valueOf(true);

同样是传入一个true作为参数,两种方法有什么区别呢?

静态工厂方法的优点

优点1:它们有名称
假如我们想要提供多个具有相同签名的构造器,这在Java中是做不到的,除非把参数列表的顺序做些调整,但这会对用户很不友好。因此可以使用静态工厂方法,取不同的名字以表示不同的构造方式。

优点2:不必每次都创建新对象
适用于单例模式。

优点3:构成基于接口的框架
静态工厂方法返回对象所属的类可以是后来动态添加的。我们以服务提供者框架(Service Provider Framework)为例讲解,该框架的代表是JDBC API。

优点4:创建泛型类实例的代码更为简洁
请看下面两种创建泛型类实例的方式,后者比前者更为简洁。

//使用构造器创建
Map<String, List<String>> m1 = new HashMap<String, List<String>>();
//使用静态工厂方法创建
Map<String, List<String>> m2 = HashMap.newInstance();

前提是HashMap提供的静态工厂方法newInstance定义如下

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

这种情况下,编译器可以通过返回值类型推断K、V的具体类型。

静态工厂的缺点

类如果不含有共有的或者受保护的构造方法,就不能被子类化。
当使用静态工厂时,就是一个普通的static方法,在API文档中,构造方法有单独的区域,而静态方法不会被分割出来。

我们一定要考虑使用静态工厂!

 

 

 

二、遇到多个构造器参数时要考虑用构建器

当创建对象的时候需要大量的可选参数,那么静态工厂和构造器就不是好的选择。可以采用的方式:

1、重叠构造器:提供第一个只有必要参数的构造器,第二个构造器包含一个可变参数 然后两个可变参数一次类推 用this( )来调用 直到所有的可变参数都包含。
但是当有很多参数的时候,客户端代码会很难写 并且难阅读。

2、javaBeans模式 用setter 对属性进行赋值,来设置必要参数和可变参数 但是当构造过程被分到了几个调用中,在构造过程中javaBeans会出现不一致的状态,即多线程的情况。

3、一种好的模式(Builder模式)
不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法来生成不可变的对象。
bulder可以是多个可变的参数。
对多个参数加约束条件时 可以用setter进行设置

构建器缺点:
1.构造器写起来很复杂
2.创建对象开销比较大
所以构建器模式只适用于需要传入很多种情况参数的时候,比如大于4种参数的配合,才比较划算。

posted on 2017-10-29 13:12  嘚吧嘚吧嘚  阅读(250)  评论(0编辑  收藏  举报