为什么工厂方法被声明为受保护的?
Why is the factory method declared as protected?
我正在阅读 Head First Design Patterns 一书,在第 4 章的 "Declaring a factory method" 部分,该方法被声明为受保护的:
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare(); // other methods follow
return pizza;
}
protected abstract Pizza createPizza(String type);
}
这让我很困惑,因为我最初认为,事实上书中也有说明,拥有一个工厂(方法)可以让你有一个地方为你创建一个实例,而不仅仅是为了以后的行动还有 "querying"。
"acting on" 我的意思是 pizza.cut()
等, "querying" 我的意思是 pizza.isSpicy()
.
protected
关键字不会将查询限制为仅子 class 和相同包 class 吗?如果第 3 方 class 需要在点餐前知道披萨是辣的怎么办?
我可能想多了,因为突出显示框没有说它必须是 protected
但它在示例代码中。
This confuses me because I initially thought, in fact it is also stated in the book, that having a factory (method) allows you to have a single place that creates an instance for you, not just for acting on later but also for "querying"
如果您希望客户端(即调用代码)控制 Pizza
何时“创建”,那么您不会使 createPizza
方法受保护;这将是一个 public 方法,任何引用 PizzaStore
实例的人都可以调用它。
如果你考虑 class,orderPizza
的语义明显不同于 createPizza
- 前者处理请求资源的调用者,而后者处理获取该资源,无论是创建新资源还是重新使用旧资源。
所以在这种情况下,很明显 PizzaStore
class 想要保留对披萨实际“创建”时间的控制,这就是它受到保护的原因。 (还因为从 PizzaStore
继承的 class 也可以实现该方法 - 如果它是私有的,则无法看到它以实现它 - 请注意,由于它是抽象的,所以 subclass 已 实施)。因此,创建过程(正如 Ananthu 也提到的那样)安全地封装在商店中。
让我们假设 Pizza
的实际“创建”是一个非常昂贵的操作;我们不希望任何人来决定它何时发生。因此,通过保护工厂方法,它允许 PizzaStore
做出如下决定(伪代码,我不知道 Java):
public abstract class PizzaStore {
protected PizzaBin bin;
//customer orders a pizza
public Pizza orderPizza(String type) {
//maybe we already have one...
Pizza pizza = HeresOneWeMadeEarlier(type);
if (pizza !=null) return pizza;
//nope, we have none, so we have to make one.
pizza = createPizza(type);
pizza.prepare(); // other methods follow
return pizza;
}
//customer returns a pizza
public void ReturnPizza(Pizza pie) {
if(!pie.HasAllSlices()){
throw new CannotReturnPartiallyEatenPizzaException();
}
//hmm. maybe we can re-use this later on...
bin.store(pie);
}
//check if we have a pizza in the bin.
protected Pizza HeresOneWeMadeEarlier(String type){
if(bin.contains(type)){
//we never said this was a *nice* pizza store!
return bin.takeOutAndDustOff(type);
}
else{
return null;
}
}
protected abstract class Pizza createPizza(String type);
}
也许不是一个吃披萨的好地方,但我希望你明白我的意思:)
By "acting on" I mean pizza.cut() etc, and by "querying" I mean pizza.isSpicy().
请记住,这些是 Pizza
上的方法,而不是 PizzaStore
上的方法,因此它们在这里并没有真正发挥作用 - 当调用者被赋予 Pizza
,他们将能够调用 Pizza
具有的任何 public 方法(eat
、cut
、share
等)和 PizzaStore
可能对它不再有任何兴趣了。
希望对您有所帮助。
更新
只是为了解决你也有一点:
What if a 3rd-party class needed to know that the pizza is spicy before ordering?
在那种情况下,您将在 PizzaStore
上设计一个方法,该方法将提供成分或选项列表,以及它们是否辛辣。
- 然后当客户点披萨(指定选项列表)时,他们已经根据他们的选项列表知道它是否辣。
- 另一个客户,如果他们有订单号,大概能够查找订单的详细信息,其中包括在请求比萨饼时选择的选项,因此也可以确定比萨饼是否是辣不辣
我正在阅读 Head First Design Patterns 一书,在第 4 章的 "Declaring a factory method" 部分,该方法被声明为受保护的:
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare(); // other methods follow
return pizza;
}
protected abstract Pizza createPizza(String type);
}
这让我很困惑,因为我最初认为,事实上书中也有说明,拥有一个工厂(方法)可以让你有一个地方为你创建一个实例,而不仅仅是为了以后的行动还有 "querying"。
"acting on" 我的意思是 pizza.cut()
等, "querying" 我的意思是 pizza.isSpicy()
.
protected
关键字不会将查询限制为仅子 class 和相同包 class 吗?如果第 3 方 class 需要在点餐前知道披萨是辣的怎么办?
我可能想多了,因为突出显示框没有说它必须是 protected
但它在示例代码中。
This confuses me because I initially thought, in fact it is also stated in the book, that having a factory (method) allows you to have a single place that creates an instance for you, not just for acting on later but also for "querying"
如果您希望客户端(即调用代码)控制
Pizza
何时“创建”,那么您不会使createPizza
方法受保护;这将是一个 public 方法,任何引用PizzaStore
实例的人都可以调用它。如果你考虑 class,
orderPizza
的语义明显不同于createPizza
- 前者处理请求资源的调用者,而后者处理获取该资源,无论是创建新资源还是重新使用旧资源。所以在这种情况下,很明显
PizzaStore
class 想要保留对披萨实际“创建”时间的控制,这就是它受到保护的原因。 (还因为从PizzaStore
继承的 class 也可以实现该方法 - 如果它是私有的,则无法看到它以实现它 - 请注意,由于它是抽象的,所以 subclass 已 实施)。因此,创建过程(正如 Ananthu 也提到的那样)安全地封装在商店中。
让我们假设 Pizza
的实际“创建”是一个非常昂贵的操作;我们不希望任何人来决定它何时发生。因此,通过保护工厂方法,它允许 PizzaStore
做出如下决定(伪代码,我不知道 Java):
public abstract class PizzaStore {
protected PizzaBin bin;
//customer orders a pizza
public Pizza orderPizza(String type) {
//maybe we already have one...
Pizza pizza = HeresOneWeMadeEarlier(type);
if (pizza !=null) return pizza;
//nope, we have none, so we have to make one.
pizza = createPizza(type);
pizza.prepare(); // other methods follow
return pizza;
}
//customer returns a pizza
public void ReturnPizza(Pizza pie) {
if(!pie.HasAllSlices()){
throw new CannotReturnPartiallyEatenPizzaException();
}
//hmm. maybe we can re-use this later on...
bin.store(pie);
}
//check if we have a pizza in the bin.
protected Pizza HeresOneWeMadeEarlier(String type){
if(bin.contains(type)){
//we never said this was a *nice* pizza store!
return bin.takeOutAndDustOff(type);
}
else{
return null;
}
}
protected abstract class Pizza createPizza(String type);
}
也许不是一个吃披萨的好地方,但我希望你明白我的意思:)
By "acting on" I mean pizza.cut() etc, and by "querying" I mean pizza.isSpicy().
请记住,这些是 Pizza
上的方法,而不是 PizzaStore
上的方法,因此它们在这里并没有真正发挥作用 - 当调用者被赋予 Pizza
,他们将能够调用 Pizza
具有的任何 public 方法(eat
、cut
、share
等)和 PizzaStore
可能对它不再有任何兴趣了。
希望对您有所帮助。
更新
只是为了解决你也有一点:
What if a 3rd-party class needed to know that the pizza is spicy before ordering?
在那种情况下,您将在 PizzaStore
上设计一个方法,该方法将提供成分或选项列表,以及它们是否辛辣。
- 然后当客户点披萨(指定选项列表)时,他们已经根据他们的选项列表知道它是否辣。
- 另一个客户,如果他们有订单号,大概能够查找订单的详细信息,其中包括在请求比萨饼时选择的选项,因此也可以确定比萨饼是否是辣不辣