工厂模式【简单工厂+工厂+抽象工厂】总结

news2025/1/12 6:09:07

一、简单工厂模式

  1. 描述
    • 简单工厂模式是属于创建型模式,又叫做静态工厂方法模式,但不属于23种GOF设计模式之一。
    • 简单工厂模式中专门定义一个简单工厂类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
    • 简单工厂类根据传入的参数,动态决定应该实例哪一个类。这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。
  2. UML 类图
    在这里插入图片描述
  3. 优点
    • 对象的创建和对象本身业务分离,降低系统的耦合度
    • 客户类不需要知道所创建的具体产品类的类名以及创建过程,只需要知道具体产品类所对应的参数即可。
    • 简单工厂可以动态实例对象,灵活性高
  4. 缺点
    • 不符合开闭原则,每次添加新对象就需要修改工厂类的判断逻辑。
    • 在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

二、工厂方法模式

  1. 描述
    • 工厂方法模式又称为工厂模式,也叫多态工厂模式,它属于类创建型模式。
    • 工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
  2. UML 类图
    在这里插入图片描述
  3. 优点
    • 符合了开闭原则,扩展时不必去修改原来的代码。
    • 符合单⼀职责原则,每个⼯⼚只负责⽣产对应的产品。
    • 一个调用者想创建一个对象,只要知道其名称就可以了。
    • 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
  4. 缺点
    • 每加一个产品,都需要加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
    • 抽象产品只能生产一种产品。
  5. 简单工厂模式与工厂方法模式区别
    • 简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
    • 工厂方法模式加入了“开放-封闭原则”(软件实体类、模块或者函数等等,应该可以扩展,但是不可以修改),将简单工厂的内部判断逻辑,移动到了客户端代码来进行,在扩展新功能的时候,简单工厂模式要修改工厂类,工厂方法模式要修改客户端
    • ⼯⼚⽅法模式引⼊⼯⼚等级结构,解决了简单⼯⼚模式中⼯⼚类职责过重的问题。

三、抽象工厂模式

  1. 描述
    • 抽象工厂模式又称为Kit模式,属于对象创建型模式。
    • 抽象工厂模式:提供一个接口,用于创建一系列相关或相互依赖对象的家族,而无需指定它们具体的类。
  2. 产品族和产品等级
    • 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品;
      • 如比亚迪生产电动车、燃油车和混动车,则比亚迪电动车位于电动车产品族中。
    • 产品等级:产品等级结构指的是产品的继承结构;
      • 如一个抽象类是电动车,其子类有比亚迪电动车、五菱电动车、长安电动车等一系列的子类,则抽象类汽车和他的具体品牌子类就构成了一个产品等级结构。

产品等级结构和产品族结构示意图如下:
在这里插入图片描述

  1. UML 类图
    在这里插入图片描述
  2. 优点
    • 易于交换产品系列,只需要改变具体工厂即可使用不同的产品配置。
    • 让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离。
    • 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
    • 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
  3. 缺点
    • 开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)
  4. 工厂方法模式与抽象工厂模式的区别在于:
    • 工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例。
    • 抽象工厂模式拥有多个抽象产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类也可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例
  5. 代码实现
    实体层
//user表
public class User {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

//department表
public class Department {
    private int id;
    private String department_name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getDepartment_name() {
        return department_name;
    }

    public void setDepartment_name(String department_name) {
        this.department_name = department_name;
    }
}

定义AbstractProductA和 AbstractProductB


public interface IUser {
    void insert(User user);
}

public interface IDepartment {
    void insert(Department department);
    }

创建具体类

//sql
class SQLServerUser implements IUser {

    @Override
    public void insert(User user) {
        System.out.println("在SQL Server中给User表加一条记录");
    }
}
class AccessUser implements IUser{

    @Override
    public void insert(User user) {
        System.out.println("在Access 中给User表加一条记录");

    }
}


class SQLServerDepartment implements IDepartment {

    @Override
    public void insert(Department department) {
        System.out.println("在SQL Server中给department 表加一条记录");
    }
}

class AccessDepartment implements IDepartment{

    @Override
    public void insert(Department department) {
        System.out.println("在Access 中给department表加一条记录");

    }
}

创建抽象⼯⼚接⼝

public interface IFactory {
    IUser createUser();
    IDepartment createDepartment();
}

具体工厂

class SQLServerFactory implements IFactory{

    @Override
    public IUser createUser() {
        return new SQLServerUser();
    }

    @Override
    public IDepartment createDepartment() {
        return new SQLServerDepartment();
    }
}
class AccessFactory implements IFactory{

    @Override
    public IUser createUser() {
        return new AccessUser();
    }

    @Override
    public IDepartment createDepartment() {
        return new AccessDepartment();
    }
 public static void main(String[] args) {
	User user = new User();
	IFactory factory = new SQLServerFactory();
    IUser iu = factory.createUser();
    iu.insert(user);
}

用反射+抽象工厂的数据访问程序

public class DataAccess {
 public static IUser getUser(String server) {
        try {
            //获取Class对象
            Class<?> sql_server = Class.forName("设计模式.抽象工厂与反射." + server +"User");
            //new SQLServerUser();
            Constructor<?> con = sql_server.getDeclaredConstructor();
            return (IUser) con.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static IDepartment getDepartment(String server){
        try {
            //获取Class对象
            Class<?> sql_server = Class.forName("设计模式.抽象工厂与反射." + server +"Department");
            //new SQLServerUser();
            Constructor<?> con = sql_server.getDeclaredConstructor();
            return (IDepartment) con.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
  }
public static void main(String[] args) {
 	    User user = new User();
	    Scanner sc = new Scanner(System.in);
        System.out.println("请输入数据库:");
        String server = sc.next();
        IUser iUser = DataAccess.getUser(server);
         iUser.insert(user);
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

wireshark工具详解、数据包抓取分析、使用教程

Wireshark界面 Wireshark查看数据捕获列表 数据包概要信息窗口&#xff1a;描述每个数据包的基本信息。如图&#xff0c;点击某行数据&#xff0c;即可在下方显示该数据包的信息。 1、数据包解析窗口&#xff1a;显示被选中的数据包的解析信息&#xff0c;包含每个数据包的整体…

通过request请求和servlet实现注册跳转界面案例及问题解决

案例&#xff1a;用户登录 * 用户登录案例需求&#xff1a; 1.编写login.html登录页面 username & password 两个输入框 2.使用Druid数据库连接池技术,操作mysql&#xff0c;day14数据库中user表 3.使用JdbcTemplate技术封装JDBC 4.登录成功跳转到Suc…

机器人操作系统ROS(19) 雷达和摄像头融合的资料

搜集的有关雷达和摄像头融合的资料。仅供参考&#xff1a; #1 传感器融合&#xff1a;激光雷达摄像头 摄像头产生的数据是2D图像&#xff0c;对于物体的形状和类别的感知精度较高。深度学习技术的成功起源于计算机视觉任务&#xff0c;很多成功的算法也是基于对图像数据的处理…

图神经网络 | Python基于图卷积的U-Net架构进行交通流量和速度的预测

图神经网络 | Python基于图卷积的U-Net架构进行交通流量和速度的预测 目录 图神经网络 | Python基于图卷积的U-Net架构进行交通流量和速度的预测效果分析基本描述程序实现核心概念参考资料效果分析 基本描述 此版本包含了训练和评估模型的代码,以预测Traffic4Cast挑战数据的交…

ssh-keygen和openssl的区别

OpenSSL OpenSSL是用于应用程序的软件库&#xff0c;该应用程序可保护计算机网络上的通信免遭窃听或需要识别另一方的身份&#xff0c;是SSL和TLS协议的开源实现。采用C语言作为开发语言&#xff0c;具备了跨平台的能力&#xff0c;支持Unix/Linux、Windows、Mac OS等多种平台…

力扣LeatCode算法题第9题-回文数

要求&#xff1a; //给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 //回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 //例如&#xff0c;1…

百世的数智化供应链凭何融入企业生命周期?

在供应链这个词出现前&#xff0c;供应链的本体就已经存在。 萨缪尔森说&#xff0c;现代经济生活的命脉是交换。当不同的物资、资金、信息在产业链上流动起来时&#xff0c;产业才能形成模型&#xff0c;经济才会有活力。然而&#xff0c;供应商增加、活动变多、地理距离拉长…

智慧气象解决方案-最新全套文件

智慧气象解决方案-最新全套文件一、建设背景二、建设架构传统气象所面临的挑战&#xff1a;1、气象数据大幅快速增长&#xff0c;导致计算能力不足2、人工智能应用不足&#xff0c;短临预报精度较低3、气象数据分散&#xff0c;数据融合困难4、气象服务方式单一&#xff0c;体验…

外卖项目04---菜品管理业务开发

效果展示: 目录 一、文件上传下载 50 1.1文件上传 50​编辑 1.2文件下载 1.3文件上传下载---文件上传代码实现1 1.4文件上传下载---文件上传代码实现2 1.5文件上传下载---文件下载代码实现 53 二、新增菜品 54 2.1需求分析 54 2.2数据模型 2.3新增菜品---代码开发--…

uniapp使用nfc功能及详解

公司使用uniapp在android手机端要增加一个nfc识别的功能。在此记录一下实现的过程。 资料查找 我的代码逻辑主要来源于找到的这篇文章&#xff1a; uniapp-安卓NFC读取 - 我要找到我的全世界 - 博客园 文章内附有代码&#xff0c;为防止文章失效代码消失&#xff0c;在这篇文…

向中央超算平台进化 哪吒汽车发布技术品牌“浩智”

电子电气架构是汽车的“大脑和神经系统”&#xff0c;决定了智能汽车的体验上限。为了实现高阶智能&#xff0c;车企须将汽车的电子电气架构从分布式&#xff0c;向集中式转变&#xff0c;打造出中央超算平台 11月21日&#xff0c;哪吒汽车举行“浩智战略2025”全球技术品牌发布…

Mentor Xpedition VX2.11入门遇到的问题和解决方案 (1)

一、前言 平时使用AD绘制板子&#xff0c;最近又朋友强烈推荐Mentor Xpedition。说它的自动布线功能非常强。相比于pads&#xff0c;这款软件的教程很少。但好在B站还是又几个不错的视频。在相关视频的讲解下&#xff0c;慢慢入门。目前来看这款软件的易用性很差&#xff0c;操…

aws eks创建节点组的不同方式和逻辑

该问题来源于&#xff0c;eks节点组能否修改实例类型&#xff0c;不同创建方式修改节点参数的方式是否有区别。结论如下&#xff1a; eksctl创建托管节点组&#xff0c;无法通过修改启动模板修改节点类型&#xff08;在eks控制台update会报错&#xff09;&#xff0c;但是可以…

网络系统管理 - Server02配置

一、Server02系统基础环境配置 二、DISK配置服务器软RAID工作任务 三、DFS membe端配置工作任务 1.Server02系统基础环境配置 (1)请根据附件说明或提供的基础信息,配置服务器的主机名,IP 地址,创建要求的用户名及密码;

docker镜像、容器 常用命令,容器端口映射

文章目录前言一、docker基础命令二、docker镜像命令1、docker images&#xff1a;列出本地主机的镜像2、 docker search &#xff1a;查看镜像3、docker pull&#xff1a;拉取镜像4、docker rmi &#xff1a; 删除docker镜像三、docker容器命令1、环境准备2、运行容器3、启动、…

Python常见工厂函数用法

工厂函数&#xff1a;能够产生类实例的内建函数。 工厂函数是指这些内建函数都是类对象&#xff0c; 当调用它们时&#xff0c;实际上是创建了一个类实例。 Python中的工厂函数举例如下&#xff1a; int(),long(),float(),complex(),bool()aint(9.9) a 9 blong(45) b 45L ff…

JavaScript 虚拟键盘:Mindfusion JavaScript Keyboard

高度交互&#xff0c;高度可定制--JavaScript 虚拟键盘--Mindfusion JavaScript Keyboard 现在&#xff0c;您的 JavaScript 应用程序可以像本地移动应用程序一样处理屏幕输入。 特征 键盘布局 扩展、紧凑和标准布局模式。KeyboardLayout 工具可帮助您根据需要创建和排列自定义…

【Hack The Box】linux练习-- Traverxec

HTB 学习笔记 【Hack The Box】linux练习-- Traverxec &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月21日&#x1f334; &#x…

Spark学习(5)-Spark Core之RDD

1 RDD详解 1.1 为什么需要RDD 分布式计算需要: 分区控制Shuffle控制数据存储\序列化\发送数据计算API等一系列功能 这些功能, 不能简单的通过Python内置的本地集合对象(如 List\ 字典等)去完成。我们在分布式框架中, 需要有一个统一的数据抽象对象, 来实现上述分布式计算所需…

JavaScript面向对象:类的继承

继承 现实中的继承&#xff1a;子承父业&#xff0c;比如我们都继承了父亲的姓。 程序中的继承&#xff1a;子类可以继承父类的一些属性和方法。 语法&#xff1a; class Father{ // 父类 } class Son extends Father { // 子类继承父类 } 实例&#xff1a; cla…