明亮,是我的大学同学,我们一个在北京,一个在深圳,昨晚两人视频关于工厂模式聊到深夜。
明亮啊,我怎么觉得工厂模式没有用啊!
不会啊,工厂模式可是最常用的设计模式之一,你说说为啥觉得没用。
你看我给你举个例子,就以餐馆为例吧,类图如下所示,其中 FoodFactory、Food 是抽象类。
首先,如果餐馆的 cook() 通过工厂模式来创建 Food,代码如下:
代码语言:javascript复制public class Restaurant {
public Food cook() {
FoodFactory factory = new ChineseFoodFactory();
Food food = factory.createFood();
return food;
}
}
而如果不使用工厂模式,代码如下:
代码语言:javascript复制public class Restaurant {
public Food cook() {
Food food = new ChineseFood();
return food;
}
}
如果我们使用工厂模式,可以不需要知道具体创建的 Food 类,但是仍需知道具体的 Factory 类,也都要 new 一个对象出来,工厂类只是把 new Food 的逻辑封装了下,并没起到什么作用啊,而且代码还更复杂了,你说工厂模式是不是没有用?
嗯,确实如你所说,使用工厂模式会让代码变得更加复杂,这是因为我们在原有逻辑上抽象出了一个新的层次概念,但是工厂模式并不是没有用的。你之所以还没能看到工厂模式的好,是因为你还没碰到实例化的具体类容易变化的场景,而在这种场景下,工厂模式能让 Restaurant 类遵循“开放-关闭原则”。而遵循该原则的好处就是,在不修改现有代码的前提下,去搭配新的行为,让我们的代码能弹性地应对变化。
开放-关闭原则:类对扩展开放,对修改关闭。
下面给你举个变化的例子吧,例如,餐馆有一天想尝试做川菜版的中餐,在不使用工厂模式时,我们必须要去修改 Restaurant 的 cook() 方法。
代码语言:javascript复制Food food = new ChuangChineseFood();
这样是违背”修改关闭“的。而工厂模式可将实例化具体类的逻辑抽离到工厂中,当面对变化时,通过修改工厂的内部逻辑,来实现 Restaurant 的”修改关闭“。除此之外,工厂模式,通过抽象出工厂接口,让我们能可以实现 Restaurant 的“扩展开放”。我们先对 Restaurant 修改下,把 factory 由局部变量变为成员变量。这样,你便可以利用多态的机制,在运行时传入不同的 Factory 来烹饪食物。
代码语言:javascript复制public class Restaurant {
private FoodFactory factory;
public Food cook() {
Food food = factory.createFood();
return food;
}
public void setFoodFactory(FoodFactory factory) {
this.factory = factory;
}
}
例如,当你想白天中餐,晚上做西餐时,只需通过 setter 方法修改 facotry 即可。
代码语言:javascript复制if (time == DAY) {
restaurant.setFoodFactory(chineseFoodFactory);
} else {
restaurant.setFoodFactory(westernFoodFactory);
}
Food food = resuaurant.cook();
嗯,明亮,我明白你的意思了,工厂模式虽然麻烦了些,但是能让类遵循“开放-关闭原则”,从而更弹性地去应对改变。原来它这么有用,那以后所有的实例化操作我都使用工厂模式,让我的代码具有超强的弹性,弹~弹~弹~
别逗了,万万不可,并不是所有地方都要使用,只有当实例化具体类容易变化时,使用工厂模式才是合适的,才需要考虑进一步的抽象。而对于不容易变化的实例化操作,是不需要遵循“开放-关闭原则”的,不然就是过度设计了。而如何判断实例化操作是否容易变化,这就需要我们的经验了。
过度设计啊,真有种装X失败的感觉。
哈哈哈,你现在知道工厂模式并非无用了吧。别再小瞧设计模式了,这可都是前人总结的宝贵经验!
禅定时刻
我之前不能理解工厂模式的用处,主要还是自己对工厂模式所需解决的问题不清楚。只有应对实例化具体类容易改变的代码时,工厂模式才能发挥出它真正的本领。大家也要避免过度设计,避免装X失败。