Java之静态工厂方法

作者: 有财君 | 来源:发表于2019-04-26 22:59 被阅读37次

    著名Java书籍《Effective Java》中第一条就提到了一个原则:考虑用静态方法而不是构造器。初看这条规则的时候我还感到很费解,构造器是Java提供的构造对象的方法,为什么不是首选呢?

    假设有这样一个类:

    package com.example.demo;
    
    public class Dog {
        private String name;
    
        private String color;
    
        private int age;
    
        public Dog() {
        }
    
        public Dog(String name) {
            this.name = name;
        }
    
        public Dog(String name, String color, int age) {
            this.name = name;
            this.color = color;
            this.age = age;
        }
    }
    

    一条狗的属性很多,比如名字,颜色和年龄,我上面的类里有三个构造器,一个无参数的默认构造器,一个参数只有name的构造器和一个有所有三个参数的构造器。

    那么这个时候问题来了,我想加一个只有毛色color参数的构造器,因为确实有些狗我只知道它的颜色,但是这已经是不可能了:

    public Dog(String color) {
        this.color = color;
    }
    

    方法重载也是有限制的,这个构造器实际上和name构造器冲突了。

    为了实现功能,我们还是改改代码的好:

    package com.example.demo;
    
    public class Dog {
        private String name;
    
        private String color;
    
        private int age;
    
        private Dog() {
        }
    
        public static Dog newDogWithAllParam(String name, String color, int age) {
            Dog dog = new Dog();
            dog.name = name;
            dog.age = age;
            dog.color = color;
            return dog;
        }
    
        public static Dog newDogWithName(String name) {
            Dog dog = new Dog();
            dog.name = name;
            return dog;
        }
    
        public static Dog newDogWithColor(String color) {
            Dog dog = new Dog();
            dog.color = color;
            return dog;
        }
    // Getters & Setters
    }
    

    每次新建对象的时候,只需要调度需要的方法就可以了。这段代码也解释了书中提到的静态工厂方法的一个好处——有名字。通过名字我可以清楚的知道我是用什么属性去创建的对象。

    我个人很喜欢使用Guava的Lists类库来创建List:

    List<Long> list = Lists.newArrayList();
    

    这种方式可以说简洁而优雅,其实,这也是静态工厂方法取代构造器的典型案例,它的源码可以来品味一下:

    @GwtCompatible(serializable = true)
      public static <E> ArrayList<E> newArrayList() {
        return new ArrayList<>();
      }
    

    其实和我之前的代码原理上是一样的。

    《Effective Java》还提到了一条,就是静态工厂方法不必在每次被调用的时候都会产生新对象,照例要看源码,我们看一下书里提供的一段代码:

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

    在这样的语句:boolean bl = Boolean.valueOf(false); 的时候,实际上是不需要创建额外的对象的,原因在我之前写static的文章中有提及:

    Java之再看static变量

    虽然上面的例子基本上是一句废话,但是也能说明问题。

    静态工厂方法还有一个好处,就是可以返回子类型,比如我们有一个Car类,其中有一个关键的参数叫做price,我希望price>30万的返回豪车子类,price<30万的返回买菜车子类,那么代码就要这样写了:

    package com.example.demo;
    
    public class Car {
        private int price;
    
        Car() {}
    
        public static Car newCarWithPrice(int price) {
            if (price > 30 * 10000) {
                return new LuxCar();
            } else {
                return new NormalCar();
            }
        }
    }
    

    这种代码就是构造器无法实现的了。

    相关文章

      网友评论

        本文标题:Java之静态工厂方法

        本文链接:https://www.haomeiwen.com/subject/esscnqtx.html