# 先看一个例子
假如你是一个比萨店店长,现在你这样管理你的产品。
public class DependentPizzaStore { | |
public Pizza createPizza( String style, String type ){ | |
Pizza pizza = null; | |
// 合肥 / 深圳风味比萨具体实例化对象 | |
if ( style.equals("HF") ){ | |
if ( type.equals("cheese") ){ | |
pizza = new HFStyleCheesePizza(); | |
}else if ( type.equals("veggie") ){ | |
pizza = new HFStyleVeggiePizza(); | |
}else if ( type.equals("clam") ){ | |
pizza = new HFStyleClamPizza(); | |
}else if ( type.equals("pepperoni") ){ | |
pizza = new HFStylePepperoniPizza(); | |
} | |
}else if ( style.equals("SZ") ){ | |
if ( type.equals("cheese") ){ | |
pizza = new HFStyleCheesePizza(); | |
}else if ( type.equals("clam") ){ | |
pizza = new HFStyleClamPizza(); | |
}else if ( type.equals("pepperoni") ){ | |
pizza = new HFStylePepperoniPizza(); | |
} | |
}else { | |
System.out.println("Error: invalid type of pizza"); | |
return null; | |
} | |
pizza.prepare(); | |
pizza.bake(); | |
pizza.cut(); | |
pizza.box(); | |
return pizza; | |
} | |
} |
由上面代码可以看出:
- 这个版本的 PizzaStore 依赖于所有的比萨对象,因为它直接创建这些比萨对象;
- 如果这些类的实现改变了,那么可能必须修改 PizzaStore;
- 因为对于比萨具体实现的任何改变都会影响到 PizzaStore。我们说 PizzaStore 依赖于比萨的实现;
- 每增加一个比萨种类,就等于让 PizzaStore 多了一个依赖;
可以看到上面代码中,依赖对象很多。
当你实例化一个对象时,就是在依赖它的具体类。
上面的例子中,是由比萨店类来创建所有的比萨对象,而不是委托给工厂。
# 依赖倒置原则(DIP-Dependency Inversion Principle)
由上面的反例,我们可以看到,PizzaStore 是 “高层组件”,而比萨实现是 “底层组件”,很清楚地,PizzaStore 依赖这些具体的比萨类。
其实,代码里减少对于具体类的依赖是意见 “好事”。这就引出了一个 OO 设计原则,即依赖倒置原则 DIP。
依赖倒置原则定义:要依赖抽象,不要依赖具体类。
工厂方法模式是依赖倒置原则的一种体现。如图
此时高层组件 PizzaStore 和底层组件(就是这些比萨)都依赖了 Pizza 抽象。
# 遵循依赖倒置原则
- 变量不可以持有具体类的引用;
- 不要让类派生自具体类;
- 不要覆盖基类中已实现的方法;
- 高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
- 抽象不应该依赖于具体实现,具体实现应该依赖于抽象。