我正在阅读Head First Design Patterns一书和第4章中的“声明工厂方法”部分,该方法被声明为受保护:
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);
}
这让我感到困惑,因为我最初认为,书中也说过,拥有一个工厂(方法)可以让你有一个地方为你创造一个实例,而不仅仅是为了以后的行动,而且用于“查询”。
通过“行动”我的意思是pizza.cut()
等,而通过“查询”我的意思是pizza.isSpicy()
。
protected
关键字不会将查询限制为仅限于子类和同包类吗?如果第三方课程在订购前需要知道比萨饼是辣的,该怎么办?
我可能会过度思考这个问题,因为高亮框并没有说明它是protected
,但它在示例代码中就已存在。
答案 0 :(得分:2)
这让我感到困惑,因为我最初认为,书中也说过,拥有一个工厂(方法)可以让你有一个地方为你创造一个实例,而不仅仅是为了以后的行动,而且for"查询"
如果您希望客户端(即调用代码)能够控制Pizza
何时获得"创建"那么你就不会保护createPizza
方法;它将是一种公共方法,任何引用PizzaStore
实例的人都可以调用它。
如果你考虑那个类,orderPizza
的语义明显不同于createPizza
- 前者处理呼叫者要求资源,而后者处理获取资源,无论是创建新的还是重新使用旧的。
所以在这种情况下,很清楚PizzaStore
课程想要保持对披萨实际获得"创建"的时间的控制,这就是为什么它" 39;受保护。 (也因为继承自PizzaStore
的类也可以实现该方法 - 如果它是私有的,它就不能看到它以实现它 - 并注意,因为它是抽象的,一个子类有来实现它)。因此,创建过程(如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);
}
也许不是一个非常好的地方去买披萨,但我希望你明白我的意思:)。
采取行动"我的意思是pizza.cut()等,并通过"查询"我的意思是pizza.isSpicy()。
请记住,这些是Pizza
上的方法,而不是PizzaStore
,所以他们并没有真正发挥作用 - 当来电者被给予他们{{1 }},他们可以调用Pizza
所拥有的任何公开方法(Pizza
,eat
,cut
等等,而share
可能不会再也没兴趣了。
希望有所帮助。
只是为了解决你所拥有的一点:
如果第三方课程在订购前需要知道比萨饼是辣的,该怎么办?
在这种情况下,您可以在PizzaStore
上设计一种方法,列出成分或选项,以及它们是否是辛辣的。