静态工厂方法每次调用时都会创建一个新对象

Static Factory Method is creating a new object everytime its invoked

在有效 Java 中提到 "Unlike constructors static factory methods are not required to create a new object each time they're invoked"。

class Car{
     String color;
     Boolean spoiler;

     public Car(String s){
        color=s;
        spoiler = false;
     }

     public static Car redCar(){
        return new Car("red");
    }
  }

主要Class:

    Car c2 = Car.redCar();
    Car c3 = Car.redCar();        

c2和c3是不同的对象。我没有得到 "not required to create a new object each time invoked".

的上下文

因为你就是这么做的:

public static Car redCar(){
    return new Car("red");
}
        //  ^ here

如果您想 return 相同的值,您可以这样做:

private static final Car RED_CAR = new Car("red");

public static Car redCar(){
    return RED_CAR;
}

重点是调用 new Car() 总是 return 一个新实例。调用Car.newInstance()意味着Carclass可以决定做什么。

例如:

private static final Map<String, Car> CARS = new HashMap<>();

public static Car newInstance(final String colour){
    return CARS.computeIfAbsent(colour, Car::new);
}

这使用 Car 构造函数作为 method reference to the new Map.computeIfAbsent 方法,如果 Map 中尚未存在该颜色的 Car,则调用它。这是一个简单的(非线程安全的)缓存实现。

所以:

final Car one = Car.newInstance("red");
final Car two = Car.newInstance("red");
System.out.println(one == two) // true

Bloch 描述的想法是,静态工厂可以使用实例的 池或缓存 在请求时传递的实例或决定其内部逻辑来创建新实例(也可能进入缓存)。这通常只适用于 不可变对象 否则你会有一些难以跟踪的交叉对象效果。

您提供的实现不是静态工厂。您已将 class 制作如下:

class Car{
     String color;
     Boolean spoiler;
     public static final Car car = new Car("name");

     public Car getInstance(){
        return car;
     }
     private Car(String s){
        color=s;
        spoiler = false;
     }

     public static Car redCar(){
        return new Car("red");
    }
  }

and then in main you have to call

Car.getInstance();

也许汽车不是最好的例子,但请考虑一个要求,即您的工厂应该只生产每种颜色的一辆汽车。你会像这样实现它(省略不必要的属性):

class Car {
    String color;

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

    public static Car car(String color) {
        Car car = CARS.get(color);
        if (car != null) return car;
        car = new Car(color);
        CARS.put(color, car);
        return car;
    }

    private static final Map<String, Car> CARS = new HashMap<>();
}

看看Integer class and its factory method valueOf。此外,这样的工厂方法对单例很有用(尽管它们有自己的注意事项)。

您正在创建新对象,

return new Car("red");  

第一次使用静态工厂方法创建对象,然后return下次从静态工厂方法return创建相同的实例。

就像所有事情一样,程序完全按照您的要求进行。如果你的静态方法每次调用时都使用"new";然后你每次都创建新对象。

unlike constructors static factory methods are not required to create a new object each time they're invoked" 的意思是您的代码 可以 决定不调用 new;但是例如 return 一个 "cached" 对象。

意思:当你使用"new"时;你调用构造函数; Java 的语义导致创建 new 对象。没有办法阻止 had,它是硬连接到语言中的。

但是当您使用静态方法时,定义该方法的语义。

"Unlike constructors static factory methods are not required to create a new object each time they're invoked"。这并不意味着调用静态工厂方法 必然 return 相同的对象(如您的示例所示),只是它 可能 (与构造函数不同)。

您可以,例如,以不同的方式实现 redCar(),这样它总是 return 是同一个对象:

class Car{
     /* snipped */

     private static final RED = new Car("red");

     public static Car redCar(){
        return RED;
     }
}

工厂的工作是创建一个对象。如果不想暴露对象的创建方式,则将创建隐藏在工厂下。

最近我碰巧在处理一个用例,其中单例的概念是根据一些附加限制定义的。例如,所有捕获 file1.txt 的文件对象都是单例(或相同的对象)。类似地,捕获 file2.text 的文件对象是单例的。但是捕获 file1.text 和 file2.text 的文件对象是不同的。

为此,创建一个静态全局列表,添加您所谓的静态对象(例如,基于文件名)。如果您不想将单例(再次基于文件)对象添加到此列表,请重写 equals。

现在,如果有人要求工厂给你一个与你在 equals 中指定的对象相匹配的对象(无论什么参数使两个对象相等),搜索全局列表,如果该对象存在 return 它,否则创建一个新对象,将其添加到列表中,然后 return 对象。

故事的寓意是,您不必 return 从工厂购买新物品。您可以根据需要调整 Singleton(如果您不需要纯 Singleton)。并且通过使用静态工厂方法,可以调用 ClassName.factory 而无需实例化它。