工厂设计模式:简单工厂、工厂方法、抽象工厂
- 面向接口编程示意图:
- 相关概念:产品、抽象产品、产品蔟、产品等级
- 产品:类
- 抽象产品:抽象类和接口
- 产品蔟:多个有内在联系,或者是有关系的产品
简单工厂:解耦了客户端与服务器代码
//抽象产品
interface Food{
public void eat();
}
//具体产品
class Hamburger implements Food{
public void eat() {
System.out.println("吃汉堡包!");
}
}
//#######################################
public class Solution {
public static void main(String[] args) {
Food f = new Hamburger();
f.eat();
}
}
这种设计相当脆弱,为什么呢?因为只要作者修改了具体产品的类名,那么客户端代码也要一起随着改变。这样服务器端代码和客户端代码就是耦合的。我们希望的效果是无论服务器端的代码如何修改,客户端代码都应不知道,这样就不用修改客户端代码。
5. 针对这种耦合关系,使用简单工厂设计模式
6. 简单工厂的优点:
a. 把具体产品的类型,从客户端代码种,解耦出来
b. 服务器端如果修改了具体产品的类名,客户端也不知道。这便符合了面向接口编程的思想。
7. 简单工厂的缺点:
a. 客户端不得不那些常量与具体产品的映射关系
b. 如果具体产品特别多,就会变得特别臃肿,比如有100个具体的产品,则要在简单工厂的Switch种写出100个case.
c.最重要的是,变化来了,如果客户端要扩展具体代码时,就必须要扩展简单工厂的代码,这样便违法了开闭原则。
8. 简单工厂的UML类图:UML类图:简单建模语言
工厂方法:解决了简单工厂客服端代码无法扩展(违反开闭原则)的问题
- 针对于简单工厂的问题,使用工厂方法设计模式
- 工厂方法的优点:1. 仍然具备简单工厂的优点,服务器端修改具体类名之后,客户端不知道代码仍能继续运行。 2. 当客户端扩展一个新的产品时,不需要修改作者原来的代码,只需要扩展一个新的工厂而已。(工厂的名字,是视为接口的,作者有责任,有义务,保证工厂的名字是稳定的,也就是说,虽然客户端依赖于工厂的具体类名,但是这个类名是稳定的,这些工厂的名字是趋于稳定的,变化几率很低)
- 工厂方法的缺点:如果有多个产品等级,工厂类的数量就会爆炸式增长
抽象工厂:解决了工厂方法类的爆炸性增长的问题
- 针对工厂方法的问题,当有多个产品等级式(食物、饮料),工厂类都会爆炸性增长
- 简单工厂的优点:仍然有简单工厂和工厂方法的优点,更重要的是抽象工厂把工厂类的数量减少了,无论有多少个产品等级,工厂就一套
- 抽象工厂中,可以生产多个产品,这多个产品之间,必须有内在联系,或是有逻辑关系的产品
- 抽象工厂的缺点:当产品等级变动时,要引起以前代码修改,违反开闭原则。
- 结论:当产品等级固定时,建议使用抽象工厂方法