《工厂模式在软件开发中的深度剖析与应用》

工厂模式

在软件开发的领域中,设计模式充当着解决常见问题的高效且可复用的策略角色。其中,工厂模式作为创建对象的重要设计模式,具有不可小觑的应用价值。接下来,我们将深入探讨简单工厂模式、工厂方法模式和抽象工厂模式。

一、简单工厂模式

简单工厂模式虽未被纳入 23 种经典设计模式,但可视为工厂模式的一种简化且特殊的实现方式。

(一)基础版
java 复制代码
// 咖啡产品的接口
public interface Coffee {
    void make();
}

// 美式咖啡类,实现 Coffee 接口
public class Americano implements Coffee {
    @Override
    public void make() {
        System.out.println("正在制作美式咖啡");
    }
}

// 摩卡咖啡类,实现 Coffee 接口
public class Mocha implements Coffee {
    @Override
    public void make() {
        System.out.println("正在制作摩卡咖啡");
    }
}

// 卡布奇诺咖啡类,实现 Coffee 接口
public class Cappuccino implements Coffee {
    @Override
    public void make() {
        System.out.println("正在制作卡布奇诺咖啡");
    }
}

// 简单工厂类
public class CoffeeSimpleFactory {
    /**
     * 根据传入的字符串类型创建对应的咖啡对象
     * @param type 咖啡类型的字符串
     * @return 对应的咖啡对象,如果类型不匹配则返回 null
     */
    public Coffee createCoffee(String type) {
        if ("americano".equalsIgnoreCase(type)) {
            return new Americano();
        } else if ("mocha".equalsIgnoreCase(type)) {
            return new Mocha();
        } else if ("cappuccino".equalsIgnoreCase(type)) {
            return new Cappuccino();
        }
        return null;
    }
}

​ 基础版通过传入字符串参数来决定创建的咖啡产品类型,但这种方式易出现参数输入错误的情况,且新增产品时需在工厂类中添加额外的判断逻辑。

(二)升级版

java 复制代码
// 咖啡产品的接口
public interface Coffee {
    void make();
}

// 美式咖啡类,实现 Coffee 接口
public class Americano implements Coffee {
    @Override
    public void make() {
        System.out.println("正在制作美式咖啡");
    }
}

// 摩卡咖啡类,实现 Coffee 接口
public class Mocha implements Coffee {
    @Override
    public void make() {
        System.out.println("正在制作摩卡咖啡");
    }
}

// 卡布奇诺咖啡类,实现 Coffee 接口
public class Cappuccino implements Coffee {
    @Override
    public void make() {
        System.out.println("正在制作卡布奇诺咖啡");
    }
}

// 简单工厂类(升级版)
public class CoffeeSimpleFactory {
    /**
     * 使用反射根据传入的咖啡类的 Class 对象创建对应的咖啡对象
     * @param clazz 咖啡类的 Class 对象
     * @return 对应的咖啡对象,如果 clazz 为 null 则返回 null
     * @throws Exception 反射创建对象时可能抛出的异常
     */
    public static Coffee createCoffee(Class<? extends Coffee> clazz) throws Exception {
        if (clazz!= null) {
            return clazz.newInstance();
        }
        return null;
    }
}

​ 升级版利用反射机制解决了基础版的参数准确性和扩展性问题。

(三)总结

适用场景

  • 工厂负责创建的对象数量相对较少。
  • 客户端只需提供参数,无需关注对象创建的具体流程。

优点

  • 只需传入准确参数,即可轻松获取所需对象,无需知晓内部创建细节。

缺点

  • 工厂类承担过多职责,新增产品类型时需修改判断逻辑,违背了开闭原则。
  • 面对复杂的产品结构时,扩展难度较大。

二、工厂方法模式

工厂方法模式明确了一个创建对象的接口,具体由实现该接口的子类来决定实例化的对象类别,将对象的实例化操作推迟至子类中进行。

(一)主要角色
  • 抽象工厂(Abstract Factory):定义创建产品的通用接口,为调用者提供访问具体工厂方法的途径,以创建产品。
  • 具体工厂(Concrete Factory):负责实现抽象工厂中的抽象方法,从而完成具体产品的创建工作。
  • 抽象产品(Product):确立产品的规范和标准,详细描述产品的主要特性与功能。
  • 具体产品(Concrete Product):切实实现抽象产品所定义的接口,由具体工厂负责创建,且与具体工厂之间存在一一对应的关系。
(二)代码实现
java 复制代码
// 抽象工厂
public interface CoffeeFactory {
    /**
     * 创建咖啡对象
     * @return 抽象的咖啡对象
     */
    Coffee create();
}

// 具体工厂 - 拿铁咖啡工厂
public class LatteFactory implements CoffeeFactory {
    @Override
    public Coffee create() {
        return new Latte();
    }
}

// 抽象产品
public interface Coffee {
    /**
     * 描述咖啡的制作过程
     */
    void make();
}

// 具体产品 - 拿铁咖啡
public class Latte implements Coffee {
    @Override
    public void make() {
        System.out.println("精心调配拿铁咖啡,牛奶与咖啡的完美融合");
    }
}
(三)总结

适用场景

  • 当创建对象的过程涉及大量重复的代码时。
  • 客户端(应用层)不关心产品类实例的创建和实现细节,只关注最终获取到的产品功能。
  • 当一个父类通过其子类来决定创建具体的对象类型时。

优点

  • 用户只需关注所需产品对应的具体工厂,无需操心产品的创建细节。
  • 新增产品时,符合开闭原则,只需创建新的具体工厂和具体产品类,无需修改现有代码,提高了系统的可扩展性。

缺点

  • 随着产品种类的增加,类的数量会显著增多,导致代码结构的复杂度上升。
  • 较高的抽象层次增加了系统的抽象性,对于初学者或不熟悉设计模式的开发者来说,理解和运用的难度较大。

三、抽象工厂模式

抽象工厂模式旨在提供一个创建一系列相关或相互依赖对象的接口,而无需明确指定具体的类。

(一)主要角色
  • 抽象工厂(Abstract Factory):提供了创建多个不同产品的接口,这些产品可能属于不同的等级或类别。
  • 具体工厂(Concrete Factory):实现了抽象工厂中的抽象方法,负责生成具体的一组相关或相互依赖的产品。
  • 抽象产品(Product):定义了产品的基本规范和主要特性,一个抽象工厂可能关联多个不同的抽象产品。
  • 具体产品(Concrete Product):实现了抽象产品所定义的接口,由具体的工厂进行创建,且与具体工厂之间存在多对一的关系。
(二)代码实现
java 复制代码
// 咖啡店 抽象工厂
public interface CoffeeShopFactory {
    /**
     * 创建咖啡产品
     * @return 具体的咖啡产品
     */
    Coffee createCoffee();

    /**
     * 创建甜点产品
     * @return 具体的甜点产品
     */
    Dessert createDessert();
}

// 美式风格工厂
public class AmericanFactory implements CoffeeShopFactory {
    @Override
    public Coffee createCoffee() {
        return new Americano();
    }

    @Override
    public Dessert createDessert() {
        return new Cheesecake();
    }
}

// 意式风格工厂
public class ItalyFactory implements CoffeeShopFactory {
    @Override
    public Coffee createCoffee() {
        return new Cappuccino();
    }

    @Override
    public Dessert createDessert() {
        return new Tiramisu();
    }
}

// 抽象产品 - 咖啡
public interface Coffee {
    /**
     * 描述咖啡的制作过程
     */
    void make();
}

// 具体产品 - 美式咖啡
public class Americano implements Coffee {
    @Override
    public void make() {
        System.out.println("精心调制美式咖啡,浓郁醇厚");
    }
}

// 抽象产品 - 甜点
public interface Dessert {
    /**
     * 描述甜点的品尝方式
     */
    void enjoy();
}

// 具体产品 - 芝士蛋糕
public class Cheesecake implements Dessert {
    @Override
    public void enjoy() {
        System.out.println("尽情享受美味的芝士蛋糕,香甜可口");
    }
}
(三)总结

产品族:指一系列紧密相关、相互关联的产品集合。

产品等级:指处于同一继承体系或具有相似性质的产品类别。

适用场景

  • 当客户端(应用层)不依赖于产品类实例的创建和实现细节时。
  • 强调一系列相关的产品对象(属于同一产品族)需协同工作,且创建这些对象的过程存在大量重复代码时。
  • 当需要为客户端提供一个统一的产品类库,使所有产品以相同的接口呈现,从而降低客户端对具体实现的依赖时。

优点

  • 能够确保当一个产品族中的多个对象协同工作时,客户端始终使用来自同一产品族的对象,保证了产品的一致性和协调性。

缺点

  • 当产品族中需要新增一个产品时,所有相关的工厂类都需要进行修改,这可能导致较大的代码改动和潜在的风险。
相关推荐
奋进的芋圆20 分钟前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin37 分钟前
设计模式之桥接模式
java·设计模式·桥接模式
model200537 分钟前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉1 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国1 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882481 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈2 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_992 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹2 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理
专注_每天进步一点点2 小时前
【java开发】写接口文档的札记
java·开发语言