【精选】设计模式——工厂设计模式

工厂设计模式是一种创建型设计模式,其主要目的是通过将对象的创建过程封装在一个工厂类中来实现对象的创建。这样可以降低客户端与具体产品类之间的耦合度,也便于代码的扩展和维护。
在这里插入图片描述
在这里插入图片描述

工厂设计模式:

以下是Java中两个常见的工厂设计模式示例:
在这里插入图片描述

1. 简单工厂模式

在这里插入图片描述

简单工厂模式又称静态工厂模式,通过一个工厂类统一创建各种不同类型的产品对象。下面以创建不同形状的图形为例。

// 定义图形接口
interface Shape {
    void draw();
}

// 实现具体图形类
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a circle.");
    }
}

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle.");
    }
}

class Triangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a triangle.");
    }
}

// 简单工厂类
class ShapeFactory {
    // 根据传入参数创建对应的图形对象
    public static Shape createShape(String shapeType) {
        if (shapeType.equalsIgnoreCase("circle")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("rectangle")) {
            return new Rectangle();
        } else if (shapeType.equalsIgnoreCase("triangle")) {
            return new Triangle();
        }
        return null;
    }
}

// 使用示例
public class SimpleFactoryExample {
    public static void main(String[] args) {
        Shape circle = ShapeFactory.createShape("circle");
        circle.draw(); // 输出:Drawing a circle.

        Shape rectangle = ShapeFactory.createShape("rectangle");
        rectangle.draw(); // 输出:Drawing a rectangle.

        Shape triangle = ShapeFactory.createShape("triangle");
        triangle.draw(); // 输出:Drawing a triangle.
    }
}

2. 工厂方法模式

工厂方法模式定义了一个创建对象的接口,但具体由子类决定实例化哪个类。下面以创建不同类型的日志记录器为例。

// 定义日志记录器接口
interface Logger {
    void log(String message);
}

// 实现具体日志记录器类
class FileLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("Writing log to file: " + message);
    }
}

class ConsoleLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("Writing log to console: " + message);
    }
}

// 抽象工厂类
abstract class LoggerFactory {
    // 创建日志记录器对象
    public abstract Logger createLogger();
}

// 具体工厂类,用于创建文件日志记录器
class FileLoggerFactory extends LoggerFactory {
    @Override
    public Logger createLogger() {
        return new FileLogger();
    }
}

// 具体工厂类,用于创建控制台日志记录器
class ConsoleLoggerFactory extends LoggerFactory {
    @Override
    public Logger createLogger() {
        return new ConsoleLogger();
    }
}

// 使用示例
public class FactoryMethodExample {
    public static void main(String[] args) {
        LoggerFactory fileLoggerFactory = new FileLoggerFactory();
        Logger fileLogger = fileLoggerFactory.createLogger();
        fileLogger.log("Error occurred."); // 输出:Writing log to file: Error occurred.

        LoggerFactory consoleLoggerFactory = new ConsoleLoggerFactory();
        Logger consoleLogger = consoleLoggerFactory.createLogger();
        consoleLogger.log("Warning."); // 输出:Writing log to console: Warning.
    }
}

好的,下面继续介绍另外两个常见的工厂设计模式示例:

3. 抽象工厂模式

抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。下面以创建不同操作系统的界面组件为例。

// 定义操作系统界面组件接口
interface Button {
    void render();
}

interface TextField {
    void render();
}

// 实现Windows操作系统界面组件
class WindowsButton implements Button {
    @Override
    public void render() {
        System.out.println("Rendering a Windows button.");
    }
}

class WindowsTextField implements TextField {
    @Override
    public void render() {
        System.out.println("Rendering a Windows text field.");
    }
}

// 实现Mac操作系统界面组件
class MacButton implements Button {
    @Override
    public void render() {
        System.out.println("Rendering a Mac button.");
    }
}

class MacTextField implements TextField {
    @Override
    public void render() {
        System.out.println("Rendering a Mac text field.");
    }
}

// 抽象工厂接口
interface GUIFactory {
    Button createButton();
    TextField createTextField();
}

// 具体工厂类,用于创建Windows风格的界面组件
class WindowsGUIFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public TextField createTextField() {
        return new WindowsTextField();
    }
}

// 具体工厂类,用于创建Mac风格的界面组件
class MacGUIFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacButton();
    }

    @Override
    public TextField createTextField() {
        return new MacTextField();
    }
}

// 使用示例
public class AbstractFactoryExample {
    public static void main(String[] args) {
        // 创建Windows风格的界面组件
        GUIFactory windowsFactory = new WindowsGUIFactory();
        Button windowsButton = windowsFactory.createButton();
        windowsButton.render(); // 输出:Rendering a Windows button.
        TextField windowsTextField = windowsFactory.createTextField();
        windowsTextField.render(); // 输出:Rendering a Windows text field.

        // 创建Mac风格的界面组件
        GUIFactory macFactory = new MacGUIFactory();
        Button macButton = macFactory.createButton();
        macButton.render(); // 输出:Rendering a Mac button.
        TextField macTextField = macFactory.createTextField();
        macTextField.render(); // 输出:Rendering a Mac text field.
    }
}

抽象工厂模式可以创建一系列相关的产品对象,例如上述示例中的不同操作系统的界面组件。使用此模式可以确保所创建的产品对象是相互配套的。

4. 单例工厂模式

单例工厂模式通过工厂类控制只创建一个对象实例,供客户端使用。下面以创建数据库连接对象为例。

// 数据库连接类
class DBConnection {
    private static DBConnection instance;

    // 私有构造函数,防止通过new关键字创建实例
    private DBConnection() {}

    public static synchronized DBConnection getInstance() {
        if (instance == null) {
            instance = new DBConnection();
        }
        return instance;
    }

    public void connect() {
        System.out.println("Connecting to the database...");
    }
}

// 使用示例
public class SingletonFactoryExample {
    public static void main(String[] args) {
        DBConnection connection1 = DBConnection.getInstance();
        connection1.connect(); // 输出:Connecting to the database...

        DBConnection connection2 = DBConnection.getInstance();
        connection2.connect(); // 输出:Connecting to the database...

        System.out.println(connection1 == connection2); // 输出:true,表示只创建了一个实例
    }
}

单例工厂模式确保在整个应用程序中只有一个实例被创建和共享,避免了多次创建相同对象的开销,并且能够提供全局访问点以便于其他对象使用。

工厂设计模式具有以下优点:

  1. 解耦客户端和具体产品类:工厂类负责对象的创建,客户端只需要通过工厂类获取所需的对象,无需直接与具体产品类交互,从而降低了客户端与具体产品类之间的耦合度。
  2. 代码的扩展性和维护性好:当需要增加新的产品时,只需添加相应的产品类和对应的工厂方法即可,不需要修改已有的代码,符合开闭原则(对扩展开放,对修改关闭)。
  3. 更好地封装和隐藏了对象的创建过程:客户端无需关心对象的创建细节,只需调用工厂类的方法即可得到所需的对象。
  4. 提高了程序的可扩展性:通过工厂类统一创建对象,可以方便地切换产品系列或者替换具体的工厂类,符合依赖倒置原则。

然而,工厂设计模式也存在一些缺点:

  1. 增加了系统的复杂度:引入工厂类会增加系统的类和对象数量,增加了代码量和理解难度。
  2. 不够灵活:由于工厂类负责对象的创建,如果需要创建具有不同特性的对象,可能需要修改工厂类的代码,违反了开闭原则。
  3. 难以扩展新的产品族:当需要扩展一个新的产品族时,需要修改工厂类的代码,违反了开闭原则。

因此,在使用工厂设计模式时需要根据实际情况权衡其优缺点,并选择最适合的设计方案。

除了上述列举的几种工厂设计模式,还有一些其他的变体和衍生形式:

  1. 多个工厂方法:某些情况下,可以在抽象工厂类中定义多个工厂方法,每个工厂方法分别用于创建不同类型的产品对象。这样可以更加灵活地处理不同类型的产品。
  2. 延迟初始化工厂:在工厂类中使用延迟初始化技术,只有在需要时才创建具体产品对象。这样可以节省系统资源,提高性能。
  3. 反射工厂:通过Java反射机制,根据传入的类名动态创建对象。这种方式可以在运行时动态地创建对象,灵活性更高。
  4. 简单工厂与抽象工厂结合:有时候可以将简单工厂和抽象工厂结合使用,以实现更复杂的对象创建过程。例如,在抽象工厂中定义一个工厂方法来创建简单工厂,然后再由简单工厂负责创建具体产品对象。

无论是哪种工厂设计模式,都要根据实际需求选择合适的方案。工厂设计模式在许多软件系统中都得到了广泛应用,它们能够提供良好的代码结构、可扩展性和灵活性,使得系统更易于维护和拓展。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/231899.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LCR 090. 打家劫舍 II(leetcode)动态规划

文章目录 前言一、题目分析二、算法原理1.状态表示2.状态转移方程3.初始化4.填表顺序5.返回值是什么 三、代码实现总结 前言 在本文章中,我们将要详细介绍一下LeetcodeLCR 090. 打家劫舍 II。采用动态规划解决,这是一道经典的多状态dp问题 一、题目分析…

Qt开发 之 Qt5各版本情况分析

文章目录 1、简介2、Qt5 版本归纳3、下载地址3.1、典型版本3.1.1、Qt5.0.03.1.2、Qt5.9.93.1.3、Qt5.12.12 3.2、当前Qt5最新版本 1、简介 Qt6 出生刚刚好一年的时间,已经出到6.6版本,带来了许多的新特性和改进。今天刚刚好抽空总结下陪伴 我工作这么长…

【vim】常用操作

用的时候看看,记太多也没用,下面都是最常用的,更多去查文档vim指令集。 以下均为正常模式下面操作,正在编辑的,先etc一下. 1/拷贝当前行 yy,5yy为拷贝包含当前行往下五行 2/p将拷贝的东西粘贴到当前行下…

学习Linux(2)-学习Linux命令

Linux目录结构 Linux目录结构-菜鸟教程 /bin:bin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令。 /boot:这里存放的是启动 Linux 时使用的一些核心文件,包括一些连接文件以及镜像文件。 /dev :dev 是 De…

【Vue】登录注册界面制作

1. 创建vue项目 https://blog.csdn.net/m0_67930426/article/details/134816155?spm1001.2014.3001.5502 2. 整合element-ui https://blog.csdn.net/m0_67930426/article/details/134827986?spm1001.2014.3001.5502 在view目录下创建文件 本篇内容使用到了 v-model cl…

飞天使-linux操作的一些技巧与知识点3

http工作原理 http1.0 协议 使用的是短连接,建立一次tcp连接,发起一次http的请求,结束,tcp断开 http1.1 协议使用的是长连接,建立一次tcp的连接,发起多次http的请求,结束,tcp断开ngi…

企业快递账单管理教程

快递账单管理怎么做,才能更高效?想要回答这个问题,首先我们要了解现如今企业快递账单管理的大致有哪些方式: 1、纸质化管理 纸质化管理现在虽然少见,但是我们应该挺熟悉。在电子面单面试之前,企业快递账单…

go学习笔记(17)Blob and ArrayBuffer

最近在学习go websocket的时候,在学习实验过程遇到一个比较奇怪问题。为什么我的数据返回是blob,而不是arrayBuffer?百思不得其解。 直到同事打包的时候微信小游戏遇到了一个报错。FileReader不支持。 经过在社区查询,官方答复是…

链表OJ—环形链表||

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 1、环形链表题目: 2、方法讲解: 图文解析: 代码实现: 其他的两种情况: 总结 前言 世上有两种耀眼的光芒…

leetcode刷题日志-54螺旋矩阵

思路&#xff1a; 上下左右设置四个边界 每走完一行或者一列&#xff0c;移动相应边界&#xff0c;当左边界大于右边界&#xff0c;或者上边界大于下边界时&#xff0c;结束 代码如下&#xff1a; class Solution {public List<Integer> spiralOrder(int[][] matrix) {…

temu我的订单在哪里看

在Temu平台上购物是一件令人愉快的事情&#xff0c;但有时候我们可能会忘记如何查看我们的订单。在本文中&#xff0c;我们将逐步介绍如何在Temu平台上查看您的订单&#xff0c;以便您可以轻松管理您的购物记录。 先给大家推荐一款拼多多/temu运营工具——多多情报通多多情报通…

【Vulnhub 靶场】【Hackable: III】【简单 - 中等】【20210602】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/hackable-iii,720/ 靶场下载&#xff1a;https://download.vulnhub.com/hackable/hackable3.ova 靶场难度&#xff1a;简单 - 中等 发布日期&#xff1a;2021年06月02日 文件大小&#xff1a;1.6 GB 靶场作者&…

4_CSS选择器进阶

day04_CSS选择器应用 Objective&#xff08;本课目标&#xff09; 掌握复合选择器掌握后代选择器掌握并集选择器掌握标签显示模式和转换掌握CSS背景 1. CSS复合选择器 1.1 后代选择器&#xff08;重点&#xff09; 作用&#xff1a;用来选择元素或元素组的子孙后代 案例 -…

Abaqus Creat Field Output

1、获取应力不变量 s2f33_S.getScalarField(invariantMISES) 2、获得应力分量 s2f33_S.getScalarField(componentLabel"S11") 参考&#xff1a; https://www.eng-tips.com/viewthread.cfm?qid469545

深化适老化服务——建行江门市分行成功打造首家“适老化”服务示范网点

新金融时代&#xff0c;银行物理网点要更好发挥客户面对面接触、情感交互、场景引流、生态建设等功能&#xff0c;开展特色网点建设转型势在必行。 近日&#xff0c;建行江门市分行恩平锦江支行“适老化”服务示范网点开业。走进锦江支行网点大堂&#xff0c;“暖阳港湾”四个…

SAP 批量修改IDOC内容

近第三方系统出现一个问题&#xff0c;导致IDOC发过来的数据都是错误的&#xff0c;但是因为某些原因&#xff0c;无法在第三方系统中重新发起&#xff0c;故需要批量修改IDOC的内容&#xff0c;并且重新在SAP中发起入站 经了解SAP提供了标准的事务代码可以进行简单的IDOC内容…

2023年9月8日 Go生态洞察:gopls的扩展与Go生态系统的成长

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

更改Android Studio的.android和.gradle文件夹默认位置

一、首先关闭Android Studio&#xff0c; 二、目标位置新建文件夹 这一步&#xff0c;为了省去麻烦&#xff0c;我并没有直接在我的目标位置新建文件夹&#xff0c;而是把C盘下的.android和.gradle文件夹整个复制过来&#xff0c;和SDK都在同一目录下&#xff0c;感觉这样可以…

Qt之实现文字滚动效果

一.效果 二.实现 roller.h #ifndef ROLLER_H #define ROLLER_H#include <QWidget> #include <QPaintEvent> #include <QShowEvent> #include <QHideEvent> #include <QTimer>class Roller : public QWidget { public:explicit Roller(QWidget …

【序列化】概念及二叉树序列化、反序列化的两种方式

序列化是什么&#xff1f;为什么需要序列化&#xff1f; 前言&#xff1a; &#xff08;1&#xff09;进程想要运行&#xff0c;就要向操作系统申请内存空间&#xff0c;进程对数据的所有操作都是在内存空间中完成的。内存中有一部分数据很重要&#xff0c;我们希望将这些数据存…