静态工厂方法每次调用时都会创建一个新对象
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()
意味着Car
class可以决定做什么。
例如:
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 而无需实例化它。
在有效 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()
意味着Car
class可以决定做什么。
例如:
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 而无需实例化它。