1 考虑使用静态工厂方法替代构造方法

静态工厂方法,指的是类中的静态方法,用于创建类的工厂方法;

和设计模式中的工厂方法主要区别在于

先看下Boolean的静态工厂方法实例吧

public final class Boolean implements java.io.Serializable,
                                      Comparable<Boolean>
{
    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code true}.
     */
    public static final Boolean TRUE = new Boolean(true);

    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code false}.
     */
    public static final Boolean FALSE = new Boolean(false);
                                   
    public static Boolean valueOf(String s) {
        return parseBoolean(s) ? TRUE : FALSE;
    }                                      
  }

工厂方法的简单工厂,抽象工厂就不写了;但是静态工厂方法和静态单例模式还是挺像的,比如

public class Singleton{
    //lazy
    private static Singleton instance = null;
    
    //private防止直接构造
    private Singleton(){}
    
    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

静态工厂方法的优点

缺点

综上,给出两种较好的实现:一种是单例模式,线程安全的静态方法;一种如下

public class RandomIntGenerator {
    /**
     * 最小值
     */
    private int min = Integer.MIN_VALUE;
    /**
     * 最大值
     */
    private int max = Integer.MAX_VALUE;

    /**
     * 大于min 小于max
     * @param min
     * @param max
     */
    public RandomIntGenerator(int min, int max)
    {
        this.min = min;
        this.max = max;
    }
    
    /**
     * 大于min 小于max
     * @param min
     * @param max
     */
    public static RandomIntGenerator between(int min, int max)
    {
        return new RandomIntGenerator(min, max);
    }
    /**
     * 大于min 小于Integer.MAX_VALUE
     */
    public static RandomIntGenerator biggerThan(int min)
    {
        return new RandomIntGenerator(min, Integer.MAX_VALUE);
    }

    /**
     * 大于Integer.MIN_VALUE 小于max
     */
    public static RandomIntGenerator smallerThan(int max)
    {
        return new RandomIntGenerator(Integer.MIN_VALUE, max);
    }

    public static RandomIntGenerator getInstance(){
        return new RandomIntGenerator(Integer.MIN_VALUE, Integer.MAX_VALUE);
    }
}

使用体验

2 当构造方法参数过多时使用builder模式

构造方法比较多的时候,比较几种构造设计

使用Builder模式的优势

缺点:

综合考虑

最佳实践1

使用体验

3 使用私有构造方法或枚举实现单例模式

讨论了3种实现单例模式的优劣,分别是

书中最倾向使用枚举来实现单例,原因如下:

其次是静态工厂的模式,优点在于

缺点在于,小心序列化问题(第11章有讨论)

为了防止单例类变成可序列化的,仅仅将添加 implements Serializable 到声明中是不够的。我们必须声明所有的实例字段为 transient,并提供一个 readResolve 方法。否则每当序列化的实例被反序列化时,都会创建一个新的实例,代码实现如下:

public class Singleton implements Serializable {
 //私有无参构造函数
 private Singleton() {}

 //单例对象
 private static final Singleton instance = new Singleton();

 //静态工厂方法
 public static Singleton getInstance() {
     return instance;
 }

 //提供该方法,以便重新指定反序列化得到的对象.
 public Object readResolve() {
     return instance;
 }
}

使用体验

  1. 确实有见过比较大的枚举,里面记录了各种单例服务实例的情况,spring之前的情况;

  2. 至于spring的单例模式,需要探究下

    [spring怎么实现单例模式?](https://www.cnblogs.com/nickup/p/9800120.html)

    可以看到,spring其实使用的是私有属性+公开的方法实现的,但是对单例做了单独的管理的;

    线程安全直接针对的这个单例的map去做的

    public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{  
           /** 
            * 充当了Bean实例的缓存,实现方式和单例注册表相同 
            */  
           private final Map singletonCache=new HashMap();  
           public Object getBean(String name)throws BeansException{  
               return getBean(name,null,null);  
           }  
        ...  
           public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{  
              //对传入的Bean name稍做处理,防止传入的Bean name名有非法字符(或则做转码)  
              String beanName=transformedBeanName(name);  
              Object bean=null;  
              //手工检测单例注册表  
              Object sharedInstance=null;  
              //使用了代码锁定同步块,原理和同步方法相似,但是这种写法效率更高  
              synchronized(this.singletonCache){  
                 sharedInstance=this.singletonCache.get(beanName);  
               }  
              if(sharedInstance!=null){  
                 ...  
                 //返回合适的缓存Bean实例  
                 bean=getObjectForSharedInstance(name,sharedInstance);  
              }else{  
                ...  
                //取得Bean的定义  
                RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false);  
                 ...  
                //根据Bean定义判断,此判断依据通常来自于组件配置文件的单例属性开关  
                //<bean id="date" class="java.util.Date" scope="singleton"/>  
                //如果是单例,做如下处理  
                if(mergedBeanDefinition.isSingleton()){  
                   synchronized(this.singletonCache){  
                    //再次检测单例注册表  
                     sharedInstance=this.singletonCache.get(beanName);  
                     if(sharedInstance==null){  
                        ...  
                       try {  
                          //真正创建Bean实例  
                          sharedInstance=createBean(beanName,mergedBeanDefinition,args);  
                          //向单例注册表注册Bean实例  
                           addSingleton(beanName,sharedInstance);  
                       }catch (Exception ex) {  
                          ...  
                       }finally{  
                          ...  
                      }  
                     }  
                   }  
                  bean=getObjectForSharedInstance(name,sharedInstance);  
                }  
               //如果是非单例,即prototpye,每次都要新创建一个Bean实例  
               //<bean id="date" class="java.util.Date" scope="prototype"/>  
               else{  
                  bean=createBean(beanName,mergedBeanDefinition,args);  
               }  
        }  
        ...  
           return bean;  
        }  
    }