破解代码:深入解析Java工厂模式

面试室里的工厂模式:小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诚恳地补充,"它有它的优点和缺点。"

  • 优点:

    1. **解耦代码:**客户端和具体类的实现分离,方便扩展。
    2. **灵活性:**增加新产品时,只需新增工厂类,符合开闭原则。
    3. **复用性:**工厂模式集中管理对象创建逻辑,减少冗余代码。
  • 缺点:

    1. **增加复杂度:**每新增一个产品,就需要新增一个工厂类。
    2. **不适合简单场景:**如果对象创建逻辑很简单,用工厂模式反而显得臃肿。

总结:设计模式的本质

小A最后说道:"工厂模式的本质,是一种面向接口编程的思想。我们通过抽象接口,隔离了对象的实现细节,同时增强了代码的可扩展性。"

"不过,设计模式是工具,而不是束缚。使用工厂模式时,要根据实际需求权衡它的适用性。最重要的,是写出既优雅又符合业务需求的代码。"


面试官微微一笑:"不错,小A。接下来的问题,我们聊聊单例模式吧。"

小A心里松了一口气:看来这一关稳了!

相关推荐
Marktowin2 小时前
Mybatis-Plus更新操作时的一个坑
java·后端
赵文宇2 小时前
CNCF Dragonfly 毕业啦!基于P2P的镜像和文件分发系统快速入门,在线体验
后端
程序员爱钓鱼2 小时前
Node.js 编程实战:即时聊天应用 —— WebSocket 实现实时通信
前端·后端·node.js
Libby博仙3 小时前
Spring Boot 条件化注解深度解析
java·spring boot·后端
源代码•宸3 小时前
Golang原理剖析(Map 源码梳理)
经验分享·后端·算法·leetcode·golang·map
小周在成长3 小时前
动态SQL与MyBatis动态SQL最佳实践
后端
瓦尔登湖懒羊羊4 小时前
TCP的自我介绍
后端
小周在成长4 小时前
MyBatis 动态SQL学习
后端
子非鱼9214 小时前
SpringBoot快速上手
java·spring boot·后端
我爱娃哈哈4 小时前
SpringBoot + XXL-JOB + Quartz:任务调度双引擎选型与高可用调度平台搭建
java·spring boot·后端