第1条:考虑用静态工厂方法代替构造器

Posted MachineChen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第1条:考虑用静态工厂方法代替构造器相关的知识,希望对你有一定的参考价值。

通常我们创建对象的方法有两种:

  1. 使用类公有的构造器

  2. 使用类的静态方法返回一个实例对象

静态方法的优点:

1.静态工厂方法与构造器不同的第一大优势在于,它们有名称

静态工厂方法的名字由自己命名,而构造方法必须与类名相同。

//使用构造器方法获取到一个素数
BigInteger prime = new BigInteger(int, int ,Random);
//使用静态工厂方法
BigInteger prime = BigInteger.probablePrime(int, Random);

我们可以通过静态工厂方法名明确知道我们要获取到的是一个素数。

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

构造方法每次调用都会创建一个对象,而静态工厂方法则不会每次调用时都创建要给对象。

静态方法通常会使用预先构建好的实例或者将构建好的实例缓存起来,进行重复利用,从而避免创建不必要的重复对象,比如我们常见的单例模式。

public class Singleton  /* * 利用一个静态变量来记录Singleton类的唯一实例 */

    private static Singleton uniqueInstance; /* * 声明为private,使得只有Singleton类内才可以调用构造器 */

    private Singleton() 
     /* * 通过该方法实例化对象,并返回这个实例 */
    public static Singleton getInstance() 
        if (uniqueInstance == null) 
            uniqueInstance = new Singleton();
        

        return uniqueInstance;
    

上面为懒惰式单例模式,工程中不能用。

3.静态工厂方法可以返回原返回类型的任何子类型对象

这样使我们在选择返回对象的类时就有了更大的灵活性。

class Father 
    private Father() 
    

    public static Father newInstance(String type) 
        if (type.equals("ChildA"))  // 根据类型判断返回那个子类对象
            return new ChildA();
         else 
            return new ChildB();
        
    

    public void getName()  
        System.out.println("My name is father");
    

    private static class ChildA extends Father 
        public void getName()  
            System.out.println("My name is child A");
        
    

    private static class ChildB extends Father 
        public void getName() 
            System.out.println("My name is child B");
        
    


public class Test 
    public static void main(String[] args) 
        Father c1 = Father.newInstance("ChildA");
        c1.getName();
        Father c2 = Father.newInstance("ChildB");
        c2.getName();
    

4.静态工厂方法在创建参数化类型实例的时候,可以使代码变得更加简洁

//构造方法 
Map<String,List<String>> map = new HashMap<String,List<String>>(); 
//静态方法 public static <K,V> HashMap<K,V> newInstance()
    return new HashMap<K,V>(); 

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

但实际上,现在Java最新的版本已经构造函数已经不需要补充参数了。

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

静态方法的缺点:

1.类如果不含有公有的类或者受保护的构造器,就不能被子类化

2.它们与其他的静态方法实际上没什么区别,因此我们约定了一些静态工厂方法的常用名称:

valueOf——不太严格的讲,该方法返回的实例与它的参数具有相同的值。这样的静态工厂方法实际上是类型转换方法。

of——valueOf的一种更为简洁的替代,在EnumSet中使用并流行起来。

getInstance——返回的实例是通过方法的参数描述的,但是不能够说与参数具有同样地值。对于Singleton来说,该方法没有参数,并返回唯一的实例。

newInstance——像getInstance一样,但newInstance能够确保返回的每个实例都与所有其他实例不同。

getType——像getInstance一样,但是在工厂方法处于不同的类中的时候使用。Type表示工厂方法所返回的对象类型。

newType——像newInstance一样,但是在工厂方法处于不同的类中的时候使用。Type表示工厂方法所返回的对象类型。

简而言之,静态工厂方法和共有构造器都各有用处,我们需要理解他们各自的长处。静态工厂通常合适,因此切忌第一反应就是提供共有的构造器,而不先考虑静态工厂。

以上是关于第1条:考虑用静态工厂方法代替构造器的主要内容,如果未能解决你的问题,请参考以下文章

第1条:考虑用静态工厂方法代替构造器

用静态工厂方法代替构造器遇到多个构造器参数时要考虑用构建器

读书笔记 - Effective Java01. 考虑用静态工厂方法代替构造器

第一条:考虑用静态工厂方法代替构造器

考虑用静态工厂方法代替构造器的场景

EffectiveJava读书笔记——考虑用静态工厂方法代替构造器