面试室里的工厂模式:小A的答题现场
面试那天,小A坐在面试官对面,手心冒了一点汗。
面试官一脸淡定地问:"小A,你对工厂模式熟悉吗?能聊聊它的用法和优缺点吗?"
小A心想:终于来了!这是我复习过的内容!他调整了下呼吸,露出一个自信的微笑:"当然,工厂模式可是我写代码的时候经常用到的设计模式之一。要不,我就从简单工厂开始聊起?"
开场:什么是工厂模式?
小A拿起桌上的笔,随手画了几个圈:"我们用个简单的比喻,工厂模式就像现实中的商品工厂。工厂根据订单的需求生产不同的产品。比如说,你下单要一杯咖啡,我就送你拿铁;你说要奶茶,OK,我立刻送你一杯珍珠奶茶。客户并不需要关心这杯饮料是怎么做出来的,只要知道下单就能拿到它。"
他继续解释:"在程序中,工厂模式的作用和这个例子一样,就是把对象创建的复杂过程隐藏起来,只暴露出一个简单的接口。这样,用户用起来更轻松,代码也更灵活。"
第一步:简单工厂模式
小A接着说:"举个简单工厂的例子吧!比如说我有个SimpleFactory
类,专门用来生成饮料。"
他用笔写下了一段代码:
typescript
// 饮料接口
interface Drink {
void serve();
}
// 具体产品
class Coffee implements Drink {
public void serve() {
System.out.println("Here is your Coffee!");
}
}
class Tea implements Drink {
public void serve() {
System.out.println("Here is your Tea!");
}
}
// 简单工厂
class SimpleFactory {
public static Drink createDrink(String type) {
if (type.equalsIgnoreCase("coffee")) {
return new Coffee();
} else if (type.equalsIgnoreCase("tea")) {
return new Tea();
} else {
throw new IllegalArgumentException("Unknown drink type!");
}
}
}
"在这个工厂里,SimpleFactory
负责创建不同的饮料,而客户代码只需要调用它的createDrink
方法,完全不用关心饮料是怎么生成的。"
第二步:工厂方法模式
面试官点了点头,小A知道要升级难度了。他擦了擦手心,说:"不过呢,简单工厂有个小问题。如果我想增加一种新的饮料,比如说奶昔,就得修改SimpleFactory
类。这违背了开闭原则,对扩展开放、对修改关闭。"
小A继续说:"所以我们有了工厂方法模式,每个产品都对应一个工厂。比如现在我要生产奶昔和果汁,我可以这样设计:"
csharp
// 工厂接口
interface DrinkFactory {
Drink createDrink();
}
// 具体工厂
class CoffeeFactory implements DrinkFactory {
public Drink createDrink() {
return new Coffee();
}
}
class TeaFactory implements DrinkFactory {
public Drink createDrink() {
return new Tea();
}
}
他补充道:"这样一来,每次增加新的饮料,只需要新建一个工厂类,而不用修改原有的代码结构。"
第三步:真实场景------支付系统
小A看了看面试官的表情,发现他还挺有兴趣,于是决定再深入一点:"工厂模式不仅仅是一个教学例子,实际上它在很多场景下都很实用。我就用支付系统来举个例子吧!"
"假设我们有不同的支付方式:支付宝支付、微信支付。用户只需要选择支付方式,不需要关心支付的内部逻辑。用工厂模式实现起来就很简单:"
typescript
// 支付接口
interface Payment {
void pay(double amount);
}
// 具体支付方式
class Alipay implements Payment {
public void pay(double amount) {
System.out.println("Paid " + amount + " using Alipay.");
}
}
class WeChatPay implements Payment {
public void pay(double amount) {
System.out.println("Paid " + amount + " using WeChat Pay.");
}
}
// 工厂
class PaymentFactory {
public static Payment createPayment(String type) {
if ("Alipay".equalsIgnoreCase(type)) {
return new Alipay();
} else if ("WeChatPay".equalsIgnoreCase(type)) {
return new WeChatPay();
}
throw new IllegalArgumentException("Unsupported payment type!");
}
}
"现在,当我调用PaymentFactory.createPayment("Alipay")
时,就能生成一个支付宝支付对象,去完成支付操作了。"
第四步:优缺点
"工厂模式虽然好用,但也不是万能的,"小A诚恳地补充,"它有它的优点和缺点。"
-
优点:
- **解耦代码:**客户端和具体类的实现分离,方便扩展。
- **灵活性:**增加新产品时,只需新增工厂类,符合开闭原则。
- **复用性:**工厂模式集中管理对象创建逻辑,减少冗余代码。
-
缺点:
- **增加复杂度:**每新增一个产品,就需要新增一个工厂类。
- **不适合简单场景:**如果对象创建逻辑很简单,用工厂模式反而显得臃肿。
总结:设计模式的本质
小A最后说道:"工厂模式的本质,是一种面向接口编程的思想。我们通过抽象接口,隔离了对象的实现细节,同时增强了代码的可扩展性。"
"不过,设计模式是工具,而不是束缚。使用工厂模式时,要根据实际需求权衡它的适用性。最重要的,是写出既优雅又符合业务需求的代码。"
面试官微微一笑:"不错,小A。接下来的问题,我们聊聊单例模式吧。"
小A心里松了一口气:看来这一关稳了!