简单工厂、工厂方法 、抽象工厂模式之间的联系

news2025/7/21 0:21:57

概念

1.简单工厂: 简单工厂模式中工厂为具体工厂,产品为抽象产品,由工厂实例创建产品实例。
2.工厂方法模式: 定义一个用于创建对象的接口,让其子类确定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
3.抽象工厂模式: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

1.简单工厂案例及解析

类图:
在这里插入图片描述
这是一个简单工厂的类图,我们可以从一个案例中来对它进行讲解:
比如小明突发奇想,想做一个关于计算器的编程代码,小明第一次编写代码时,将所有的代码都写在一个类里面,而且只有加减乘除四种方法。
从上述的描述中,我们不难看出,如果我们在添加一个功能的话,那么只能在本类中进行更改,在多添加十个功能,那么最后可能只有自己才能看懂。所以,我们使用简单工厂来进行改进。

代码:

运算类

public class Operation {
    private double numberA=0;
    private double numberB=0;

    public double getNumberA() {
        return numberA;
    }

    public void setNumberA(double numberA) {
        this.numberA = numberA;
    }

    public double getNumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }

    public  double GetResult(){
        double result = 0;
        return result;
    }
}

其他具体逻辑类

public class OperationAdd extends Operation{

    @Override
    public double GetResult(){
        double result = 0;
        result=getNumberA()+getNumberB();
        return result;
    }
}



public class OperationSub extends Operation{

    @Override
    public double GetResult(){
        double result = 0;
        result=getNumberA()-getNumberB();
        return result;
    }
}



public class OperationMul extends Operation{

    @Override
    public double GetResult(){
        double result = 0;
        result=getNumberA()*getNumberB();
        return result;
    }
}



public class OperationDiv extends Operation{

    @Override
    public double GetResult(){
        double result = 0;
        if (getNumberB()==0) {
            System.out.println("除数不能为零!");

        }else {
            result=getNumberA()/getNumberB();
        }

        return result;
    }
}

简单运算工厂类

public class OperationFactory {
    public static Operation createOperate(String operate){
        Operation oper=new Operation();
        switch (operate){
            case "+":
                oper=new OperationAdd();
                break;
            case "-":
                oper=new OperationSub();
                break;
            case "*":
                oper=new OperationMul();
                break;
            case "/":
                oper=new OperationDiv();
                break;
        }
        return oper;
    }
}

客户端代码

public class Text {
    public static void main(String[] args) {
        Operation op=OperationFactory.createOperate("+");
        op.setNumberA(1);
        op.setNumberB(2);
        double result = op.GetResult();
        System.out.println(result);
    }
}

实现

3.0

总结:
在简单工厂里面,客户端操作人员,不需要知道具体的逻辑,只要进行数字的输入和运算的字符输入,即可知道最后的答案。而且我们在修改其中的某一个具体的类时,也不会影响到其他的类。

特点:使用静态的方法通过接收参数的不同来返回不同的实例。

缺点:当我们添加新的开跟或者平方等其他运算时,就违反了开放-封闭原则。

优点:灵活性高。在工厂类中包含了必要的逻辑,根据客户端的条件动态的实例化相关的类,对客户端来说,去掉了与产品的具体依赖。

2.工厂方法案例及解析

类图:
在这里插入图片描述
解析:
不难看出,工厂方法是简单工厂的迭代升级,现在是由具体的工厂来进行每个类的实例化。

我们在这里再看一个案例,小明的同学小红,继承了雷锋精神。经常到一个老人家中帮忙,近几天,小红得了病不能再去帮助老人了,就委托了小明和社区的志愿者去老人家中帮忙。

代码:

雷锋类:

public class LeiFeng {
    public void Sweep(){
        System.out.println("扫地");
    }

    public void Wash(){
        System.out.println("洗衣");
    }

    public void BuyRice(){
        System.out.println("买米");
    }
}

学生和社区志愿者继承雷锋类:

public class Undergraduate extends LeiFeng{

}

public class Volunteer extends LeiFeng {
}

雷锋工厂

public interface IFactory {
    LeiFeng CreateLeiFeng();
}

继承雷锋精神的人

学生工厂:

public class UndergraduateFactory implements IFactory {
    @Override
    public LeiFeng CreateLeiFeng() {
        return new Undergraduate();
    }
}

社区志愿者工厂:

public class VolunteerFactory implements IFactory {
    @Override
    public LeiFeng CreateLeiFeng() {
            return new Volunteer();
    }
}

客户端代码:

public class Test {
    public static void main(String[] args) {
        IFactory factory=new UndergraduateFactory();
        LeiFeng student=factory.CreateLeiFeng();

        student.Sweep();
        student.BuyRice();
        student.Wash();
    }
}

实现:

扫地
买米
洗衣

总结:
工厂方法针对每一个继承雷锋类的人提供一个工厂类,如果我们还要添加其他继承雷锋精神的人,那么直接添加类即可。

缺点:不易于维护,假如某个具体类要进行修改,很可能需要修改对应的工厂类。当同时修改多处代码时,对工厂类的修改就会变得相当的麻烦。

优点:创建对象的接口,让子类去决定具体实例化的对象,把内部逻辑判断转移到客户端代码。工厂方法克服了简单工厂违背开放-封闭原则的缺点,不用每次新增新类型产品都修改工厂类,又保持了封装对象创建过程的优点。

3.抽象工厂案例及解析

类图:
在这里插入图片描述
案例:
这天,小明在工作时遇到一个项目,项目的要求是:客户现在希望自己的数据可以从两种数据库的存取数据,并且现在有两张表,每个表都有一个添加和查询的方法。

那么我们怎么实现具体的代码呢?

IUser接口

public interface IUser {
    void Insert(User user);
    User GetUser(int id);
}
public interface IDepartment {
    void Insert(Department department);
    User GetUser(int id);
}
public interface IFactory {
    IUser CreateUser();
    IDepartment CreateDepartment();
}

Sqlserver数据库对应操作所创建的类

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

    @Override
    public User GetUser(int id) {
        System.out.println("在SQL server中根据ID得到user表一条记录");
        return null;
    }
}
public class SqlserverDepartment implements IDepartment {
    @Override
    public void Insert(Department department) {
        System.out.println("在SQL server中给Department表增加一条记录");
    }

    @Override
    public User GetUser(int id) {
        System.out.println("在SQL server中根据ID得到Department表一条记录");
        return null;
    }
}
public class SqlServerFactory implements IFactory {
    @Override
    public IUser CreateUser() {
        return new SqlserverUser();
    }

    @Override
    public IDepartment CreateDepartment() {
        return new SqlserverDepartment();
    }
}

从这里开始就是 Access数据库对应操作所创建的类

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

    @Override
    public User GetUser(int id) {
        System.out.println("在Access中根据ID得到user表一条记录");
        return null;
    }
}

public class AccesssDepartment implements IDepartment {
    @Override
    public void Insert(Department department) {
        System.out.println("在Access中给Department表增加一条记录");
    }

    @Override
    public User GetUser(int id) {
        System.out.println("在Access中根据ID得到Department表一条记录");
        return null;
    }
}

public class AccessFactory implements IFactory {
    @Override
    public IUser CreateUser() {
        return new AccessUser();
    }

    @Override
    public IDepartment CreateDepartment() {
        return new AccesssDepartment();
    }
}

客户端代码:

public static void main(String[] args) {
        User user = new User();
        Department department = new Department();

        //IFactory factory=new SqlServerFactory();
        IFactory factory=new AccessFactory();

        IUser iu=factory.CreateUser();
        iu.Insert(user);
        iu.GetUser(1);

        IDepartment id=factory.CreateDepartment();
        id.GetUser(1);
        id.Insert(department);

    }

输出代码:

Access中给user表增加一条记录
在Access中根据ID得到user表一条记录
在Access中根据ID得到Department表一条记录
在Access中给Department表增加一条记录

总结:
看完代码,我们可以看出抽象工厂模式是对于工厂方法的迭代升级,抽象工厂模式是针对于多对多的关系。可以增加新的产品线(方法)。

缺点:抽象工厂模式在于难以应付“新对象”的需求变动,比如我在加一个数据库。难以支持新种类的产品。

优点:分离具体的类,客户端通过抽象接口操纵实例,产品的类名也在具体工厂实现中被分离,不会出现在客户端代码中。

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

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

相关文章

Docker中部署elasticsearch

Docker中部署elasticsearch1.下载镜像2.查看镜像是否下载成功3.选择挂载硬盘创建三个目录,分别对应es的日志,es的配置,和es的插件。并设置目录权限为可读写。4.进入config目录里创建elasticsearch.yml文件,并使用vi命令插入如下内…

windows下app爬虫环境搭建:python + fiddler + Appium + 夜神模拟器

夜神模拟器自行下载安装 1、安装java https://www.oracle.com/java/technologies/downloads/#jdk19-windows 配置环境变量 系统环境下 在Path下添加 验证安装情况 打开 cmd 命令行工具,输入 java -version,返回信息如图所示表示安装配置成功 …

11.18MyBatis 学习2

1 #和$的区别 #{}表示一个占位符号 通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。可以自动对值添加 ’ ’ 单引号 ${}表示拼接 sql 串…

【附源码】Python计算机毕业设计天气预报查询管理系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

linux x64 下的redis安装

1.官网下载linux版本的安装包,官网地址:http://redis.io/download 2.新建目录 mkdir /usr/local/src/redis,并上传到该目录,解压 tar xzvf redis-7.0.5.tar.gz 3…执行make 对Redis解压后文件进行编译 在编译完成之后查看当前文…

MeterSphereV2.3版本Mac本地启动详细教程(含常见错误)

一、准备工作 因为代码是java语言写的,所以提前准备好java的环境JDK11 :https://www.oracle.com/java/technologies/javase/jdk11-archive-downloads.htmlmaven(3.6.2以上都行):https://archive.apache.org/dist/mave…

进程的虚拟地址空间

每个程序运行起来后,都拥有一个自己的虚拟地址空间(注意是虚拟的,不是实际存在的),这个虚拟地址空间的大小由计算机的硬件平台 关于虚拟的概念,当时IBM给出了一种说法很形象生动: 它存在&#x…

XSS-labs靶场实战(三)——第7-8关

今天继续给大家介绍渗透测试相关知识,本文主要内容是XSS-labs靶场实战第7-8关。 免责声明: 本文所介绍的内容仅做学习交流使用,严禁利用文中技术进行非法行为,否则造成一切严重后果自负! 再次强调:严禁对未…

PyQt5_股票策略校验工具_升级版

相对 PyQt5_股票策略校验工具 博文,图形展示方面增加多行图展示,原本只有K线图,升级版工具可以动态添加多行指标图 股票策略有效与否的确认,需要在不同股票,不同时间段,运行对比,确认在哪些条件…

图文轻松说透 K8S Pod 各种驱逐场景

图文轻松说透 K8S Pod 各种驱逐场景 Kubernetes Pod 被驱逐是什么意思? 它们被终止,通常是没有足够资源的结果。但是为什么会这样呢? 驱逐是指派给节点的Pod 被终止的过程。Kubernetes 中最常见的情况之一是Preemption,为了在资…

基于PHP+MySQL健身俱乐部系统的设计与实现

随着时代的发展和人们对生活的热爱,健身已经成为人们工作之余的一种热爱,相对应的各种健身俱乐部也如雨后春笋般出现,处于宣传的目的各类健身俱乐部网站也不断的出现,处于对健身俱乐部的宣传作用,我们通过PHP语言和MYSQL数据库开发了健身俱乐部系统 PHP:MySQL健身俱…

笔试强训第29天(有假币+求正数数组的最小不可组成和)

单选 A选项:当内存访问越界的时候,线程会收到信号,进而进行信号处理。调用信号处理函数。 B选项:ACM时间。 A:最后访问时间,文件被读取而更新的时间 C:状态修改时间,文件的属性或者权…

pymsql模块+事务+mysql 注入+数据库备份和恢复

import pymysqlconn pymysql.connect(host127.0.0.1, userroot, password123456, databasehomework) # cur conn.cursor(cursorpymysql.cursors.DictCursor)#查询返回字典 cur conn.cursor() # cursor游标,默认返回元组 try:cur.execute(select * from students…

前端加密与解密

插件加密 MD5加密(不可逆) MD5加密是不可逆的,相当于是插件加密,当然你也可以把他的方法抄过来自己实现。 MD5.js是通过前台js加密的方式对用户信息,密码等私密信息进行加密处理的工具,前端用的比较多。…

【毕业设计】深度学习手势识别检测系统 - python

文章目录1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估6 识别效果7 最后1 前言 🔥 Hi,大家好,这里是丹成学长的毕设系列文章! 🔥 对毕设有任何疑问都可以问学长…

【ASE+python学习】批量实现将含有空位的结构进行氢饱和(实际就是在某个位置添加氢原子)

批量实现将含有空位的结构进行氢饱和任务大纲任务思路氢原子相对位置计算代码实现-单个结构加氢导入所需库/包计算氢原子坐标给结构加氢运行结果代码实现-批量结构加氢导入相关库/包遍历文件夹内所有结构,并逐次给结构加氢批量实现的逻辑与结果在搬砖过程中&#xf…

【教学类-15-01】20221115《学号(姓名)描字帖-A4横版-竖切》(中班)

效果展示 浅蓝色打印纸(灰色字体) 背景需求: 在中3班的Python学具实验中,发现至少有3位幼儿明确表示自己不会写学号,还有3位幼儿书写的学号是镜像字(两个数字位置互换、两个数字都左右镜像、2和5上下镜像等…

【树莓派不吃灰】命令篇⑤ ps -ef | grep xxx | grep -v grep | wc -l 命令

目录1. 简介2. grep -v grep 命令作用2.1 ps -ef | grep python32.2 grep -v grep❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2022-11-18 ❤️❤️ 本篇更新记录 2022-11-18 ❤️🎉 欢迎关注 🔎点赞 &am…

让 Serverless 更普惠,阿里云函数计算 FC 宣布全面降价,最大幅度达 37.5%

背景 11 月 5 日,2022 杭州 云栖大会上,阿里云宣布函数计算 FC 开启全面降价,vCPU 单价降幅 11% ,其他的各个独立计费项最高降幅达 37.5% 。 本次云栖大会上,阿里云智能总裁张建锋表示,以云为核心的新型…

动态分区算法(头歌实验)第1关:首次适应算法。第2关:最佳适应算法。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 题目: 第1关:首次适应算法 任务描述 假设初始状态下可用的内存空间为55MB,并有如下的请求序列: 作业1申请15MB 作业2申请30M…