对象对具体类的依赖

Posted

技术标签:

【中文标题】对象对具体类的依赖【英文标题】:object dependency on to concrete classes 【发布时间】:2021-04-25 13:18:45 【问题描述】:

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

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

我真的不明白它如何影响刚刚由news 启动并使用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;
  

【问题讨论】:

【参考方案1】:

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;
    

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

因此,存储依赖于抽象而不是具体。

【讨论】:

我们可以说构造函数的签名是一个实现细节吗?因为在您的第一句话中,您说 DependentPizzaStore 需要明确了解所有实现。 @snr 是的,知道构造函数签名是一个实现细节

以上是关于对象对具体类的依赖的主要内容,如果未能解决你的问题,请参考以下文章

对多个类的依赖性

面象对象设计6大原则之五:依赖倒置原则

依赖倒置原则

JAVA设计原则

《Head First 设计模式》之工厂模式

向依赖关系宣战[转]