工厂模式-小记

工厂模式-小记

    • 工厂模式
    • 简单工厂模式
      • 场景复现
      • 抽象产品接口
      • 具体产品
      • 工厂类
      • 测试方法
    • 工厂方法模式
      • 工厂方法模式
      • 场景描述
      • 抽象工厂接口
      • 具体工厂
      • 抽象产品
      • 具体产品
      • 客户端测试
    • 抽象工厂模式
      • 场景描述
      • 抽象工厂
      • 具体工厂
      • 抽象产品
      • 具体产品
      • 客户端测试
    • 三者的对比

工厂模式

工厂模式提供了一种创建对象的最佳方式,在工厂模式中,我们创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来指向新创建的对象。

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

优点:

  • 解耦:将对象的创建与使用分离,使得系统更加灵活。
  • 易于扩展:当需要增加新的咖啡类型时,只需增加新的实现类,并在工厂类中添加相应的逻辑即可,无需修改客户端代码。

缺点:

  • 增加复杂度:当系统中存在大量的产品类时,工厂类的逻辑可能会变得非常复杂。
  • 违反开闭原则:在简单工厂模式中,增加新的产品类时,通常需要修改工厂类,这违反了开闭原则(对扩展开放,对修改关闭)。

简单工厂模式

简化客户端代码,通过一个工厂类来创建对象。

场景复现

假设我们有一个咖啡店,它提供多种咖啡的制作。每种咖啡(如拿铁、卡布奇诺、美式等)的制作过程略有不同,但我们希望有一个统一的接口来订购咖啡,而不需要知道每种咖啡的具体制作过程。

抽象产品接口

咖啡接口:定义制作咖啡的方法

public interface Coffee{
    void prepareRecipe();
}

具体产品

实现咖啡接口的具体咖啡类(如Espresso、Latte、Cappuccino等)

public class Espresso implements Coffee{
    @Override
    public void prepareRecipe(){
        System.out.println("Preparing Espresso");
    }
}

public class Latte implements Coffee {
    @Override
    public void prepareRecipe() {
        System.out.println("Preparing Latte");
    }
}

工厂类

咖啡工厂类:这个类根据传入的类型信息返回相应的咖啡对象

public class CoffeeFactory {

    public static Coffee getCoffee(String type){
        if(type == null){
            return null;
        }
        if(type.equalsIgnoreCase("espresso")){
            return new Espresso();
        }else if(type.equalsIgnoreCase("latte")){
            return new Latte();
        }
        return null;
    }
}

测试方法

订购咖啡测试方法:

public static void main(String[] args) {
    Coffee myCoffee = CoffeeFactory.getCoffee("latte");

    if (myCoffee != null) {
        myCoffee.prepareRecipe();
    }
}

工厂方法模式

工厂方法模式

工厂方法模式与简单工厂模式相比,工厂方法模式提供了更高的灵活性和更好的扩展性。

定义:工厂方法模式定义了一个创建对象的接口,但允许子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类。

目的

  • 解耦:将对象的创建与使用对象的代码解耦。
  • 扩展性:当需要添加新的产品时,只需要增加新的具体工厂类,而不需要修改已有的工厂接口或客户端代码。
  • 遵循开闭原则:对扩展开放,对修改关闭。

结构

  • 抽象工厂:定义一个用于创建产品的接口。
  • 具体工厂:实现抽象工厂中的接口,完成具体产品的创建。
  • 抽象产品:定义产品的规范,描述所有实例所共有的公共接口。
  • 具体产品:由具体工厂创建的对象。

优点

  • 易于扩展:当需要添加新的图形类型时,只需要增加一个新的具体工厂类即可,不需要修改已有的工厂接口或客户端代码。
  • 解耦:客户端只依赖于抽象工厂接口,而不依赖于具体的工厂实现。
  • 遵循开闭原则:对扩展开放,对修改关闭。

缺点

  • 增加复杂性:对于每一种产品都需要一个具体的工厂类,增加了系统的复杂性。
  • 多态性限制:如果需要创建的产品具有不同的接口,则不适合使用工厂方法模式。

应用场景

  • 当系统中存在多个产品等级结构时:例如,不同的图形类。
  • 当希望客户端独立于如何创建对象以及对象的实际实现时:例如,客户端只需要知道如何获取图形对象,而不关心具体的创建逻辑。
  • 当一个类希望由它的子类来指定它所创建的对象时:例如,父类定义一个工厂方法,由子类实现具体的创建逻辑。

总结:工厂方法模式通过定义一个创建对象的接口,并让具体的子类决定实例化哪一个类,从而将对象的创建与使用对象的代码解耦。这种方式不仅提高了代码的可扩展性,而且遵循了开闭原则,使得系统更加灵活和易于维护

场景描述

创建一个图形绘制系统,支持圆形,原形,矩形和三角形。每种图形应该包含基础的绘图方法

抽象工厂接口

public interface ShapeFactory {
    Shape getShape();
}

具体工厂

为上述图形(圆形,原形,矩形和三角形)提供具体的工厂类

public class CircleFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Circle();
    }
}

public class RectangleFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Rectangle();
    }
}

public class TriangleFactory implements ShapeFactory {
    @Override
    public Shape getShape() {
        return new Triangle();
    }
}

抽象产品

public interface Shape {
    void draw();
}

具体产品

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

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

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

客户端测试

public class Client {
    public static void main(String[] args) {
        ShapeFactory circleFactory = new CircleFactory();
        Shape circle = circleFactory.getShape();
        circle.draw();

        ShapeFactory rectangleFactory = new RectangleFactory();
        Shape rectangle = rectangleFactory.getShape();
        rectangle.draw();

        ShapeFactory triangleFactory = new TriangleFactory();
        Shape triangle = triangleFactory.getShape();
        triangle.draw();
    }
}

抽象工厂模式

抽象工厂模式,提供了一种创建一系列相关或依赖对象的接口,而无需指定它们具体的类。

创建一组相关的产品对象,确保它们协同工作 (如:电脑需要有外设:键盘+鼠标+音响 才能更好的协同工作)

结构:

  • 抽象工厂:定义一个用于创建产品的几口。
  • 具体工厂:实现抽象工厂中的接口,完成具体产品的创建。
  • 抽象产品:定义产品的规范,描述所有实例共有的公共接口。
  • 具体产品:由工厂创建的对象。

优点:

  • 封装性:抽象工厂模式将产品族的创建封装在一个工厂类中,使得客户端不需要关心具体的创建逻辑。
  • 易扩展:如果需要添加新的产品族(如 Linux 风格),只需添加一个新的具体工厂类即可。
  • 一致性:保证同一产品族中的产品对象协同工作,避免了不同风格的产品混用带来的问题。

缺点:

  1. 增加复杂性:抽象工厂模式增加了系统的复杂性,因为需要定义更多的接口和类。
  2. 难以修改产品族:如果需要修改某个产品族中的产品,可能需要修改多个类。
  3. 违反开闭原则:如果需要添加新的产品类型(如新的控件),需要修改现有的工厂类。

应用场景

  • 需要创建一系列相关产品:例如,创建不同风格的界面组件。
  • 产品族中的产品需要协同工作:例如,不同风格的按钮和文本框需要一致的外观和行为。

总结:抽象工厂模式通过定义一个创建一系列相关或依赖对象的接口,使得客户端可以方便地创建一组相关的产品对象。这种方式使得系统更加模块化、易于扩展和维护。在实际应用中,抽象工厂模式特别适用于需要创建多个相关产品族的场景。

场景描述

如:QQ登录窗体,由文本输入框和按钮组合完成登录功能。对于mac,linux,win,移动端,qq的登录窗体可能展现风格是不同的或者相同的,但是基本都是由 按钮和输入框完成。此时就可以使用抽象工厂来完成。

抽象工厂

public interface GUIFactory {
    Button createButton();
    TextField createTextField();
}

具体工厂

// WindowsFactory
public class WindowsFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

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

// MacFactory
public class MacFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacButton();
    }

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

抽象产品

public interface Button {
    void paint();
}

public interface TextField {
    void paint();
}

具体产品

public class WindowsButton implements Button {
    @Override
    public void paint() {
        System.out.println("Painting a Windows button.");
    }
}

public class MacButton implements Button {
    @Override
    public void paint() {
        System.out.println("Painting a Mac button.");
    }
}

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

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

客户端测试

public class Client {
    public static void main(String[] args) {
        // 使用 Windows 风格的工厂
        GUIFactory windowsFactory = new WindowsFactory();
        Button windowsButton = windowsFactory.createButton();
        TextField windowsTextField = windowsFactory.createTextField();

        windowsButton.paint();
        windowsTextField.paint();

        // 使用 Mac 风格的工厂
        GUIFactory macFactory = new MacFactory();
        Button macButton = macFactory.createButton();
        TextField macTextField = macFactory.createTextField();

        macButton.paint();
        macTextField.paint();
    }
}

三者的对比

简单工厂 vs 工厂方法 vs 抽象工厂:

  1. 扩展性
    简单工厂模式:扩展性较差,因为需要修改工厂类来添加新的产品类型。
    工厂方法模式:扩展性较好,通过新增具体工厂类来添加新产品类型。
    抽象工厂模式:扩展性好,通过新增具体工厂类来添加新产品族,但修改产品族较难。
  2. 解耦
    简单工厂模式:客户端依赖于具体的工厂类。
    工厂方法模式:客户端依赖于抽象工厂接口。
    抽象工厂模式:客户端依赖于抽象工厂接口。
  3. 支持继承
    简单工厂模式:不支持继承。
    工厂方法模式:支持继承。
    抽象工厂模式:支持继承。
  4. 创建对象的类型
    简单工厂模式:创建单个对象。
    工厂方法模式:创建单个对象。
    抽象工厂模式:创建一系列相关对象。
  5. 适用场景
    简单工厂模式:适用于创建的对象较少,且不经常需要添加新类型的情况。
    工厂方法模式:适用于需要创建多个相关产品,并且未来可能需要添加新产品类型的情况。
    抽象工厂模式:适用于需要创建多个相关产品族,并且未来可能需要添加新产品族的情况。

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

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

相关文章

2024 年高教社杯全国大学生数学建模竞赛题目【A/B/C/D/E题】完整思路

↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ A题是数模类赛事很常见的物理类赛题,需要学习不少相关知识。此题涉及对一个动态系统的建模,模拟…

策略模式的小记

策略模式 策略模式支付系统【场景再现】硬编码完成不同的支付策略使用策略模式,对比不同(1)支付策略接口(2)具体的支付策略类(3)上下文(4)客户端(5&#xff0…

vue3获取视频时长、码率、格式等视频详细信息

前言: 我们在上传视频需要视频的帧数等信息的时候,上传组件无法直接读取帧数等信息 方法:通过mediainfo.js来获取视频的帧率、总帧数和视频的总时长 mediainfo.js地址,想详细了解的可以去看看git地址:https://githu…

【生日视频制作】海上绿色摩托艇汽车艇车身AE模板修改文字软件生成器教程特效素材【AE模板】

生日视频制作教程海上绿色摩托艇汽车艇车身AE模板修改文字特效广软件告生成神器素材祝福玩法AE模板替换工程 怎么如何做的【生日视频制作】海上绿色摩托艇汽车艇车身AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤: 安装AE软件 下载AE模板 把AE模…

Java笔试面试题AI答之JDBC(2)

文章目录 7. 列出Java应该遵循的JDBC最佳实践?8. Statement与PreparedStatement的区别,什么是SQL注入,如何防止SQL注入Statement与PreparedStatement的区别什么是SQL注入如何防止SQL注入 9. JDBC如何连接数据库?1. 加载JDBC驱动程序2. 建立数…

基于FreeRTOS的STM32多功能手表

前言 项目背景 项目演示 使用到的硬件 项目原理图 目前版本实现的功能 设计到的freertos知识 实现思路 代码讲解 初始化GPIO引脚、配置时钟 蜂鸣器初始化以及软件定时器创建 系统默认创建的defaultTaskHandle 创建七个Task,代表七个功能 ShowTimeTask …

MySQL复习2

高级查询 准备 create database greatselect; use greatselect;drop table if exists class; create table class (cid int(11) not null auto_increment,caption varchar(32) not null,primary key (cid) )engine innoDB AUTO_INCREMENT5 default charset utf8;create tab…

磁盘加密工具 | VeraCrypt v1.26.15 绿色版

VeraCrypt 是一个开源项目,旨在提供强大的加密解决方案,以创建和管理加密的磁盘分区和加密容器。它继承了著名的加密软件 TrueCrypt 的特性,并在此基础上进行了扩展和改进。 主要特性 1. 高级加密算法 VeraCrypt 支持多种加密算法&#xf…

运维学习————Jenkins(1)

目录 一、项目开发周期 二、jenkins的简介和作用 三、jenkins下载 1、使用war包安装 2、初始化配置 3、工作流程图 4、Jenkins安装配置maven和git maven git 5、jenkins安装插件 6、配置maven,git,jdk jdk配置 Git配置 Maven配置 四、修改tomcat的一些配置 五…

[网络编程]TCP和UDP的比较 及 通过java用UDP实现网络编程

文章目录 一. 网络编程套接字TCP和UDP的特点有连接 vs 无连接可靠传输 vs 不可靠传输面向字节流 vs 面向数据报全双工 vs 半双工 二. java用UDP实现网络编程代码实现:运行代码:启动多个客户端别人能否使用?实现翻译功能 一. 网络编程套接字 网络编程套接字, 就是指操作系统提…

[000-01-008].Seata案例应用

业务说明:这里我们创建三个服务,一个订单服务,一个库存服务,一个账户服务。当用户下单时,会在订单服务中创建一个订单,然后通过远程调用库存服务来扣减下单商品的库存;再通过远程调用账户服务来…

AD7606工作原理以及FPGA控制验证(串行和并行模式)

文章目录 一、AD7606介绍二、AD7606采集原理2.1 AD7606功能框图2.2 AD7606管脚说明 三、AD7606并行模式时序分析以及实现3.1 并行模式时序图3.2 并行模式时序要求3.3 代码编写3.4 仿真观察 四、AD7606串行模式时序分析以及实现4.1 串行模式时序图4.2 串行模式时序要求4.3 代码编…

使用Cskin时候 遇到按钮有默认阴影问题解决

使用Cskin时候 遇到按钮有默认阴影 设置 DrawType 属性就可以了

全网最火的AI技术:GraphRag概念详解

GraphRAG是一种结合了知识图谱(Knowledge Graph)和大语言模型(LLM)的检索增强生成(Retrieval-Augmented Generation, RAG)技术,旨在通过将结构化和非结构化数据相结合来增强生成式AI的表现。它的…

[已更新问题二三matlab+python]2024数学建模国赛高教社杯C题:农作物的种植策略 思路代码文章助攻手把手保姆级

发布于9.6 10:00 有问题后续会修正!! 问题一代码展示: 问题二代码结果展示: 问题三代码展示: https://docs.qq.com/doc/DVVVlV0NmcnBDTlVJ问题一部分代码分享: #!/usr/bin/env python # coding: utf-8# In[15]:import pandas as pd# In[16]:# 读取Excel文件 file_path 附件2…

【数学建模备赛】Ep07:灰色预测模型

文章目录 一、前言🚀🚀🚀二、:灰色预测模型☀️☀️☀️1. 灰色系统引入2. 方法3. 步骤① 累加法产生新序列② 利用部分和序列相邻两项的加权平均产生序列z③ 建立关于原始数据与序列z的灰微分方程④ 利用最小二乘法确定灰微分方程…

win10添加右键菜单打开VSCode

当进入一个文件夹后,想右键直接打开我的工程,用发现没有vscode项。本文就来介绍如何右键通过vsCode打开项目。步骤1:在桌面新建一个txt文档,用文本编辑器打开 步骤2: 查看vscode所在位置 在桌面找到vscode快捷键图标&…

【大规模语言模型:从理论到实践】Transformer中PositionalEncoder详解

书籍链接:大规模语言模型:从理论到实践 第15页位置表示层代码详解 1. 构造函数 __init__() def __init__(self, d_model, max_seq_len80):super().__init__()self.d_model d_model # 嵌入的维度(embedding dimension)d_mode…

基于springboot的二手车交易系统的设计与实现

题目:基于springboot的二手车交易系统的设计与实现 摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因…

【书籍推荐】马斯克推荐的5部经典书籍

埃隆马斯克是谁想必已经不需要介绍,世界首富都推荐过哪些值得看的好书?今天这篇文章整理了5本马斯克曾推荐过或评价值得一读的书,或许可以从中一探他改变世界的方法和奥秘。 《结构是什么》 结构高于内容,结构决定内容。内容是表…