当前位置: 首页 > article >正文

设计模式 - 简单工厂模式

目录

一、基本概念

二、组成部分

三、举例说明

3.1 定义产品接口

 3.2 定义具体产品类

3.3 定义工厂类

3.4 客户端代码

四、优缺点

4.1 优点

4.2 缺点

五、总结

5.1 适用场景

5.2 不适用场景

5.3 替代模式


简单工厂模式(Simple Factory Pattern)虽然不是 GoF 设计模式的一部分,但在实际开发中非常常见。简单工厂模式主要用于创建对象,它提供了一个静态方法来创建对象,而不是使用构造函数或工厂方法。简单工厂模式的主要目的是隐藏对象创建的细节,使客户端代码不必关心具体的创建逻辑。

一、基本概念

简单工厂模式的核心思想是定义一个工厂类,这个工厂类负责创建各种不同的产品对象。客户端通过调用工厂类的一个静态方法来获取所需的产品对象,而不需要知道产品的具体创建细节。

二、组成部分

  1. 工厂类(Factory):负责创建产品对象。
  2. 产品接口或抽象类(Product):定义了产品对象应该实现的方法。
  3. 具体产品类(Concrete Products):实现了产品接口或继承自抽象类,代表具体的对象。

三、举例说明

假设我们需要创建不同类型的披萨(Pizza),并且我们希望有一个工厂类来负责创建这些披萨。

3.1 定义产品接口

public interface Pizza {
    void prepare();
    void bake();
    void cut();
    void box();
}

 3.2 定义具体产品类

public class CheesePizza implements Pizza {
    @Override
    public void prepare() {
        System.out.println("Preparing Cheese Pizza");
    }

    @Override
    public void bake() {
        System.out.println("Baking Cheese Pizza");
    }

    @Override
    public void cut() {
        System.out.println("Cutting Cheese Pizza");
    }

    @Override
    public void box() {
        System.out.println("Boxing Cheese Pizza");
    }
}

public class PepperoniPizza implements Pizza {
    @Override
    public void prepare() {
        System.out.println("Preparing Pepperoni Pizza");
    }

    @Override
    public void bake() {
        System.out.println("Baking Pepperoni Pizza");
    }

    @Override
    public void cut() {
        System.out.println("Cutting Pepperoni Pizza");
    }

    @Override
    public void box() {
        System.out.println("Boxing Pepperoni Pizza");
    }
}

3.3 定义工厂类

public class SimplePizzaFactory {
    public Pizza createPizza(String type) {
        Pizza pizza = null;
        switch (type.toLowerCase()) {
            case "cheese":
                pizza = new CheesePizza();
                break;
            case "pepperoni":
                pizza = new PepperoniPizza();
                break;
            default:
                throw new IllegalArgumentException("Unknown pizza type: " + type);
        }
        return pizza;
    }
}

3.4 客户端代码

public class Client {
    public static void main(String[] args) {
        SimplePizzaFactory factory = new SimplePizzaFactory();
        Pizza cheesePizza = factory.createPizza("cheese");
        cheesePizza.prepare();
        cheesePizza.bake();
        cheesePizza.cut();
        cheesePizza.box();

        Pizza pepperoniPizza = factory.createPizza("pepperoni");
        pepperoniPizza.prepare();
        pepperoniPizza.bake();
        pepperoniPizza.cut();
        pepperoniPizza.box();
    }
}

 

四、优缺点

4.1 优点

  1. 封装性好:客户端不需要关心产品的创建细节,只需要知道如何使用产品。
  2. 易于扩展:当需要增加新的产品时,只需要修改工厂类,而不需要修改客户端代码。
  3. 符合开闭原则:对扩展开放,对修改关闭。

4.2 缺点

  1. 违反开闭原则:当需要增加新产品时,工厂类的代码需要修改。
  2. 类的静态方法不易扩展:如果工厂类变得庞大,难以维护。
  3. 单个工厂类包含太多逻辑:可能导致工厂类过于复杂。

五、总结

简单工厂模式通过将对象的创建逻辑封装在一个静态工厂方法中,简化了客户端代码。然而,随着产品的增加,工厂类可能会变得庞大,难以管理和维护。此外,当需要添加新的产品时,需要修改工厂类,这违反了开闭原则。

在实际应用中,可以根据项目的具体需求选择是否使用简单工厂模式。如果产品的类型相对固定,并且未来扩展的可能性较小,那么简单工厂模式是一个不错的选择。如果产品类型可能会频繁变动,那么可以考虑使用其他的创建型模式,如工厂方法模式或抽象工厂模式。

5.1 适用场景

  1. 产品种类有限

    如果产品种类相对较少且稳定,未来扩展的可能性不大,那么可以使用简单工厂模式。这样可以避免工厂类变得过于庞大。
  2. 静态方法适合场景

    如果创建的产品对象不需要复杂的创建逻辑,并且创建过程可以很好地封装在一个静态方法中,那么简单工厂模式是一个合适的选择。
  3. 减少客户端代码复杂性

    如果客户端代码需要频繁地创建产品对象,并且这些对象的创建过程需要一定的逻辑处理,那么简单工厂模式可以帮助隐藏这些逻辑,简化客户端代码。
  4. 中央控制点

    如果希望有一个中央控制点来统一管理所有产品的创建,那么简单工厂模式可以提供这样的功能。

5.2 不适用场景

  1. 产品种类经常变动

    如果产品种类在未来可能会频繁增加或删除,那么使用简单工厂模式会导致工厂类频繁修改,不利于维护。此时更适合使用工厂方法模式或抽象工厂模式。
  2. 工厂类过于庞大

    如果工厂类已经包含了大量的产品创建逻辑,那么继续在同一个类中增加更多的产品可能会导致类过于复杂,难以理解和维护。此时应该考虑重构工厂类或使用其他模式。
  3. 需要支持子类扩展

    如果希望子类能够扩展或覆盖产品的创建逻辑,那么简单工厂模式可能不是一个好的选择,因为它的静态方法不容易被继承或覆盖。这时可以考虑使用工厂方法模式。

5.3 替代模式

  1. 工厂方法模式

    如果需要支持子类扩展产品的创建逻辑,或者产品种类可能会增加,那么工厂方法模式是一个更好的选择。它允许子类通过继承来扩展产品的创建逻辑。
  2. 抽象工厂模式

    如果需要创建一系列相关的产品族,并且这些产品族之间存在依赖关系,那么抽象工厂模式更为合适。它可以创建一组相关的产品对象,而不需要指定它们的具体类。
  3. 建造者模式

    如果产品的创建过程非常复杂,涉及到多个步骤,并且这些步骤可能会发生变化,那么建造者模式可以更好地应对这种情况。

http://www.kler.cn/a/377346.html

相关文章:

  • 收集的linux命令/Docker命令/git命令
  • 完成程序《大奖赛评分B》
  • 《Rust语言圣经》Rust教程笔记17:2.Rust基础入门(2.6模式匹配)2.6.2解构Rust Option<T>
  • 微信公众号绑定设计-WeChat public platform bing and send message
  • docker 可用镜像服务地址(2024.10.31亲测可用)
  • 华为 HarmonyOS NEXT 原生应用开发: 动画的基础使用(属性、显示、专场)动画
  • 使用官网tar包制作OpenSSL及OpenSSH rpm包进行升级安装(OpenSSH_9.9p1, without OpenSSL未解决)
  • 在平衡中追寻高度:探秘AVL树的自我调节之美
  • 基础算法——排序算法(冒泡排序,选择排序,堆排序,插入排序,希尔排序,归并排序,快速排序,计数排序,桶排序,基数排序,Java排序)
  • 【已解决】element-plus配置主题色后,sass兼容问题。set-color-mix-level() is...in Dart Sass 3
  • 分布式光伏系统开发数字化解决方案
  • ASRPRO 记事本2
  • Linux——— 信号
  • Flutter加载本地HTML的优雅解决方案:轻松实现富文本展示
  • MATLAB 如何判断数据样本是否服从伽马分布(Gamma)
  • 『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC
  • ARM base instruction -- umaddl
  • Kafka 判断一个节点是否还活着有那两个条件?
  • 【代码随想录Day58】图论Part09
  • C/C++语言基础--C++模板与元编程系列三(变量模板、constexpr、萃取等…………)
  • Cpp::set map 的理解与使用(22)
  • Redis常见面试题总结(上)
  • yt-dlp下载视频
  • mac 安装tomcat
  • 从0开始学统计-数据类别与测量层次
  • Python软体中使用Pandas库读取数据并绘制柱状图的实用指南