【问题标题】:Demerit of declaring static method in AbstractFactoryAbstractFactory 中声明静态方法的缺点
【发布时间】:2016-04-11 11:20:27
【问题描述】:

根据 Head First 设计模式,在 Factory 类中声明静态方法的缺点 - “您不能子类化并更改 getPizza 方法的行为”。工厂类使用 getPizza 方法来决定返回哪种类型的对象。如果我理解正确的话,我的课是

    public class PizzaFactory {
        public static Pizza getPizza(String type) {
            if (type.equals("cheese"))
                return new CheesePizza();
            else if (type.equalsIgnoreCase("thisCrust"))
                return new ThinCrustPizza();
            return null;
        }
    }

即使方法是静态的,我也总是可以创建一个子类,例如 -

public class DelhiPizzaFactory extends PizzaFactory {
    public static Pizza getPizza(String type) {
        if (type.equals("cheese"))
            return new CheesePizza();
        else if (type.equalsIgnoreCase("thisCrust"))
            return new ThinCrustPizza();
        return null;
    }
}

我可以互换使用超类和子类。

public class PizzaStore {

    Pizza pizza;

    public void orderPizza(String type) {
        pizza = DelhiPizzaFactory.getPizza(type);
        pizza.prepare();
        pizza.bake();
    }
}

那么有什么缺点呢?

【问题讨论】:

  • 必须是final才能停止覆盖

标签: java design-patterns factory-pattern


【解决方案1】:

这是一个用例的问题。 假设您使用的 API 具有以下某些全局 API 的方法。

public void setPizzaFactory(PizzaFactory factory) {
    this.pizzaFactory=factory;
   // set pizza factory and 
}

通常,您可以将两个工厂作为参数传递给该方法,但如果我们的 API 将使用您刚刚设置的 PizzaFactory,并调用其 getPizza() 方法,它将始终使用 @ 中声明的 getPizza() 方法987654324@ 尽管您可能已经将其他派生类作为工厂对象传递了。

如果你的工厂中有非静态方法,那么你可以做类似的事情

api.setPizzaFactory(new DoubleCheesePizzaFactory) 其中DoubleCheesePizzaFactory 覆盖getPizza 方法以始终向每个比萨饼添加额外的奶酪。这样,内部“烘焙”api 将使用来自 DoubleCheesePizzaFactorygetCheese 方法版本,而不是 PizzaFactory.getPizza 版本(又名。super.getPizza

所以缺点就是这样:您无法更改 super 类中方法的行为(通过覆盖)。

【讨论】:

  • 我在 eclipse 中试过了,果然如你所说!如果我不想覆盖 getPizza 方法,那么我应该将它声明为 final。如果我只使用静态,子类将不知道他们的新实现是否会被选中。现在说得通了。谢谢!
  • 很高兴我能帮上忙。所以一般来说,声明方法 static final 没有什么意义,因为没有这样的需要——它们不会像非静态方法那样被覆盖。仅供参考 - 您将观察到使用“覆盖”私有字段的相同行为。
【解决方案2】:

由于您想防止覆盖,您需要将您的方法设为final,即。像这样:

public class PizzaFactory {
     public static final Pizza getPizza(String type) {
         [...]
}

这样,您可以防止覆盖,如果这是您在这种情况下想要的,虽然在其他情况下,是的,通过不设置 final 来允许覆盖也很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    • 2016-12-14
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-24
    相关资源
    最近更新 更多