对象依赖于具体类

问题描述

我试图理解抽象工厂模式,但它真的很难。我在 Head First Design Patterns 书中看到了以下示例,试图描述依赖关系以及为什么依赖是不好的。但是,我不明白该代码示例的以下说法。

因为比萨饼具体实现的任何变化都会影响 DependentPizzaStore,我们说 DependentPizzaStore “取决于”披萨 实现。

我真的不明白它如何影响仅由 new 启动并使用 bakecut方法的类。 DependentPizzaStore 对具体实现一无所知。

public class DependentPizzaStore {
  public Pizza createPizza(String style,String type) {
    Pizza pizza = null;
    if (style.equals("NY")) {
      if (type.equals("cheese")) {
        pizza = new NYStyleCheesePizza();
      } else if (type.equals("veggie")) {
        pizza = new NYStyleVeggiePizza();
      } else if (type.equals("clam")) {
        pizza = new NYStyleClamPizza();
      } else if (type.equals("pepperoni")) {
        pizza = new NYStylePepperoniPizza();
      }
    } else if (style.equals("Chicago")) {
      if (type.equals("cheese")) {
        pizza = new ChicagoStyleCheesePizza();
      } else if (type.equals("veggie")) {
        pizza = new ChicagoStyleVeggiePizza();
      } else if (type.equals("clam")) {
        pizza = new ChicagoStyleClamPizza();
      } else if (type.equals("pepperoni")) {
        pizza = new ChicagoStylePepperoniPizza();
      }
    } else {
      System.out.println("Error: invalid type of pizza");
      return null;
    }
    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.Box();
    return pizza;
  }
}

解决方法

DependentPizzaStore 需要明确了解所有实现才能初始化它们。因此,DependentPizzaStore 依赖于这些实现并紧密耦合。如果这些实现的构造函数中的任何一个要更改,那么您还需要更改 DependentPizzaStore

抽象工厂将允许您提供一个接口来创建相关或依赖对象的系列,而无需指定它们的具体类。

因为你的例子也有不同风格的披萨

public interface PizzaFactory {
    string getStyle();
    Pizza createPizza(String type);
}

那么不同的风格就需要不同的工厂。

public class NYStylePizzaFactory implements PizzaFactory {
    
    public string getStyle() { return "NY"; }
    
    public Pizza createPizza(String type) {
        Pizza pizza = null;
        if (type.equals("cheese")) {
            pizza = new NYStyleCheesePizza();
        } else if (type.equals("veggie")) {
            pizza = new NYStyleVeggiePizza();
        } else if (type.equals("clam")) {
            pizza = new NYStyleClamPizza();
        } else if (type.equals("pepperoni")) {
            pizza = new NYStylePepperoniPizza();
        }
        
        if(pizza == null){
            //...throw?
        }
        
        return pizza;
    }
}

public class ChicagoStylePizzaFactory implements PizzaFactory {
    
    public string getStyle() { return "Chicago"; }
    
    public Pizza createPizza(String type) {
        if (type.equals("cheese")) {
            pizza = new ChicagoStyleCheesePizza();
        } else if (type.equals("veggie")) {
            pizza = new ChicagoStyleVeggiePizza();
        } else if (type.equals("clam")) {
            pizza = new ChicagoStyleClamPizza();
        } else if (type.equals("pepperoni")) {
            pizza = new ChicagoStylePepperoniPizza();
        }
        
        if(pizza == null){
            //...throw?
        }
        
        return pizza;
    }
}

DependentPizzaStore 现在可以将制作比萨饼的任务委托给工厂,而无需了解有关实施细节的任何信息。

public class DependentPizzaStore {
    List<PizzaFactory> factories;
    
    public DependentPizzaStore(List<PizzaFactory> factories) {
        this.factories = factories;
    }

    public Pizza createPizza(String style,String type) {
        Pizza pizza = null;
        for (PizzaFactory factory : factories) {
            if (factory.getStyle().equals(style)) {
                pizza = factory.createPizza(type);
                break;
            }
        }
        if (pizza == null){
          System.out.println("Error: invalid type of pizza");
          return null;
        }
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

任何其他样式都不会影响或导致商店发生变化。工厂生产比萨的方式发生任何变化也不会影响或导致商店发生变化。

因此,商店依赖于抽象而不是具体。