Java23种设计模式之第三弹-工厂模式

news2024/10/5 5:38:06

说起工厂,我们第一反应是制作什么东西的吧~。在现实生活中,工厂 , 就是用于生成一些特定事物的厂商。

回到我们此处说的工厂模式上,什么是工厂模式呢 , 顾名思义,就是生成我们的对象的类就会称成为工厂。
我们这里说的工厂模式 包括了三种工厂模式 : 分别是 简单工厂 、工厂方法、抽象工厂。

一、简单工厂

1、简单工厂定义:

简单工厂也称为静态工厂。是一种创建型模式。在简单工厂中,可以根据传入参数的不同返回不同类的对象实例。简单工厂是一个专门的工厂类,用来创建不同其他类的实例对象。这些实例对象通常他们的父类是同一个抽象类或者接口。

2、我们为什么要使用简单工厂呢?他可以带给我们什么好处呢?

在通常的做法中,我们会将对象创建的代码写在具体的业务代码中(即使用对象的代码写到一块)。这样会存在一个问题就是——>假设使用对象的地方有多个类使用,且创建对象的过程相似。在多个使用对象的类中都需要写一遍重复的构建对象的代码。

当我们不关心对象的产生方式时,我们就可以使用简单工厂模式。

3、我们可以先看下类图

普通类图
在这里插入图片描述

简单工厂类图
在这里插入图片描述
对于简单工厂来说。如果在版本迭代的过程中,产品类(Product)初始化的相关逻辑需要更改,我们只需要修改简单工厂类中的逻辑即可。不需要修改原有的业务逻辑类,也不会产生修改此业务逻辑造成原有类中其他部分出现问题。

4、代码示例

抽象产品。

package com.starcpdk.factory.simpleFactory;

/**
 * @Author 姚云峰
 * @Email
 * @Date 2022/11/17 20:03
 * @Version 1.0
 */
public abstract class Food {
    String name;

    public Food() {
    }

    public Food(String name) {
        this.name = name;
    }

    public abstract void eat(String foodName);
    public abstract void back(String foodName);
    public abstract void cut(String foodName);
    public abstract void paper(String foodName);
}

具体产品1

package com.starcpdk.factory.simpleFactory;

/**
 * @Author 姚云峰
 * @Email
 * @Date 2022/11/17 20:07
 * @Version 1.0
 */
public class Bread extends Food{
    public Bread(String name) {
        super(name);
    }

    public Bread() {
    }

    @Override
    public void eat(String foodName) {
        System.out.println(super.name + "吃" + foodName);
    }

    @Override
    public void back(String foodName) {
        System.out.println(super.name + "烤" + foodName);
    }

    @Override
    public void cut(String foodName) {
        System.out.println(super.name + "切" + foodName);
    }

    @Override
    public void paper(String foodName) {
        System.out.println(super.name + "准备" + foodName);
    }
}

具体产品2

package com.starcpdk.factory.simpleFactory;

/**
 * @Author 姚云峰
 * @Email
 * @Date 2022/11/17 20:07
 * @Version 1.0
 */
public class Rice extends Food{

    public Rice(String name) {
        super(name);
    }

    public Rice() {
    }

    @Override
    public void eat(String foodName) {
        System.out.println(super.name + "吃" + foodName + "嘎嘎香");
    }

    @Override
    public void back(String foodName) {
        System.out.println(super.name + "烤"+ foodName + "嘎嘎旺");
    }

    @Override
    public void cut(String foodName) {
        System.out.println(super.name + "切" + foodName + "嘎嘎爽");
    }

    @Override
    public void paper(String foodName) {
        System.out.println(super.name + "准备"+ foodName +"嘎嘎愉快");
    }
}

简单工厂

package com.starcpdk.factory.simpleFactory;

/**
 * @Author 姚云峰
 * @Email
 * @Date 2022/11/17 20:03
 * @Version 1.0
 */
public class SimpleFactory {

    private SimpleFactory() {
    }

    private static Food food;

    public static Food createFood(String foodType) {
        if (foodType.equals("rice")) {
            food = new Rice("张三");
        } else if (foodType.equals("bread")) {
            food = new Bread("李四");
        }
        return food;
    }

}

客户端

package com.starcpdk.factory.simpleFactory;

/**
 * @Author 姚云峰
 * @Email
 * @Date 2022/11/17 20:16
 * @Version 1.0
 */
public class Main {
    public static void main(String[] args) {
        Food bread = SimpleFactory.createFood("bread");
        bread.eat("法师面包");
        Food rice = SimpleFactory.createFood("rice");
        rice.eat("牛奶米饭");
    }
}

5、使用场景

我们在不关注实例的创建过程时,就可以使用简单工厂模式。将类创建实例的过程交给工厂类去创建,我们只需需要去向工厂类索要实例即可。

主要是面向产品的创建,把创建由上层转移到下层。
如果项目的需求仅需new Product()能够满足后面的所有需求,依然使用最初的在业务层new 对象的方式即可。

二、工厂方法

简单工厂: 一个工厂统一负责所有产品的创建,一定会造成代码的可维护性差。相比简单工厂,工厂方法模式用一个工厂对应一类产品,创建的过程是一一对应的,也更加细颗粒度的创建,每当修改一个产品的创建过程,只需要修改产品对应的子类工厂即可。不会影响到其他产品的创建使用。将产品的创建过程延迟到工厂子类进行创建。

在这里插入图片描述

代码

package com.starcpdk.factory.factoryMethod;

public abstract class AbstractProduct {
    public abstract void paper();
}
package com.starcpdk.factory.factoryMethod;

public class Product2 extends AbstractProduct{

    @Override
    public void paper() {
        System.out.println("Product2   paper 。。。。");
    }
}
package com.starcpdk.factory.factoryMethod;

public class Product1 extends AbstractProduct{

    @Override
    public void paper() {
        System.out.println("Product1   paper 。。。。");
    }
}
package com.starcpdk.factory.factoryMethod;
public abstract class AbstractFactory {
    public abstract AbstractProduct createProduct();
}
package com.starcpdk.factory.factoryMethod;

public class Factory1 extends AbstractFactory{
    @Override
    public AbstractProduct createProduct() {
        return new Product1();
    }
}
package com.starcpdk.factory.factoryMethod;

public class Factory2 extends AbstractFactory{
    @Override
    public AbstractProduct createProduct() {
        return new Product2();
    }
}
package com.starcpdk.factory.factoryMethod;

public class Method {
    public static void main(String[] args) {

        AbstractFactory factory = new Factory1();
        AbstractProduct product = factory.createProduct();
        factory = new Factory2();
        product = factory.createProduct();
        product.paper();
        product.paper();

    }
}

总结:

相当于加了一层。在一个工厂类中生产各种产品,对单一产品的修改又或者增加产品都可能会影响到之前创建其他产品的逻辑。所以我们要加一层将创建产品的过程移至子类生产,每个工厂子类对应一个产品的生产。

  • 产品的增加和删除不会影响到其他产品的产出
  • 单个产品逻辑修改只需要在对应的工厂类修改即可,不需要动其他的工厂。
  • 职责更加明确,方便维护。

三、抽象工厂

抽象工厂是基于产品族的概念建立的。我们先想一下工厂方法模式 是 一个子类工厂对应一个子类产品。
而我们的抽象工厂相当于是 一个子类工厂对应 一些子类产品。 而这些子类产品是一类产品。比如说 我们有一个产品 他有两类描述 即形状 和 颜色。那我们可以将形状划分为一族产品 , 将颜色划分为另外一族产品。这样我们就是相当于有两个工厂类。一个去负责创建形状类产品,一个负责创建 颜色类产品。假如后期我们这个产品又增加了一族产品叫 味道,那我们只需要增加一个工厂去负责创建味道 类的产品即可。

但是形状 有长方形,正方形,圆形等。颜色有蓝色, 绿色,红色等。
这类里面会有很多的产品。抽象工厂相当于是针对一类一类划分出的工厂。而工厂方法则是针对一个一个产品划分工厂。

其实工厂方法模式是抽象工厂模式的一种特殊体。即抽象工厂中只有一个产品族时,就是我们的工厂方法模式。

假设我们有两族产品 : 现代风格。古代风格。
每族产品有两个:椅子、桌子。
那我们就有两个抽象产品 分别是椅子、桌子,然后我们有椅子对应的实际产品,桌子对应的实际产品去分别继承椅子和桌子。然后我们有一个抽象工厂。这个抽象工厂有两个方法,一个创建椅子,一个创建桌子,具体创建什么桌子或者什么椅子根据传入的参数决定。然后我们有两个具体工厂,分别是现代工厂、古代工厂。都去实现这个抽象工厂,也就是说这两个工厂都会产生桌子和椅子。具体产生什么样的桌子和什么样的椅子,由传入的参数决定。

在这里插入图片描述

代码

package com.starcpdk.factory.abstractfactory;

public abstract class ProductA {
}
package com.starcpdk.factory.abstractfactory;

public class ProductA1 extends ProductA {
}
package com.starcpdk.factory.abstractfactory;

public class ProductA2 extends ProductA {
}
package com.starcpdk.factory.abstractfactory;

public abstract class ProductB {
}
package com.starcpdk.factory.abstractfactory;

public class ProductB1 extends ProductB {
}
package com.starcpdk.factory.abstractfactory;

public class ProductB2 extends ProductB {
}
package com.starcpdk.factory.abstractfactory;

public abstract class AbstractFactory {
    public abstract ProductA createProductA();
    public abstract ProductB createProductB();
}
package com.starcpdk.factory.abstractfactory;

public class Factory1 extends AbstractFactory{
    @Override
    public ProductA createProductA() {
        return new ProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new ProductB1();
    }
}
package com.starcpdk.factory.abstractfactory;

public class Factory2 extends AbstractFactory{
    @Override
    public ProductA createProductA() {
        return new ProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ProductB2();
    }
}
package com.starcpdk.factory.abstractfactory;

public class Client {
    public static void main(String[] args) {
        Factory1 factory1 = new Factory1();
        System.out.println(factory1.createProductA());
        System.out.println(factory1.createProductB());

        Factory2 factory2 = new Factory2();
        System.out.println(factory2.createProductA());
        System.out.println(factory2.createProductB());
    }
}

总结:抽象工厂是增加一类产品方便,但是在单个产品的增加上不方便。

抽象工厂相当于是 配套的生产,增加一套容易,但是给每套增加一个就不容易了。如果要增加一个产品。即在抽象工厂中需要增加一个方法,那么实现抽象工厂的具体工厂就全部需要增加该方法。但是如果是增加一族产品,那就比较容易了 ,只需要增加一个工厂,去实现抽象工厂,然后这个工厂就会实现抽象工厂中的方法去创建对应的产品,创建的还是一大类产品,这一大类产品中的产品个数是不变的。还是一套。

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

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

相关文章

机器学习模型与backtrader框架整合

原创文章第116篇,专注“个人成长与财富自由、世界运作的逻辑, AI量化投资”。 北京疫情似乎还没有到拐点,但这三天结束后应该会到来。 今天重点说说,机器学习模型整合到我们的回测框架中,并与backtrader连接起来回测…

【Python模块】logging 日志模块

当入门一门语言时,最简单最直观的打印日志信息方式就是使用 print() 函数了,而这毕竟是自己练习和测试才会这样做。当参与项目时一定会去使用日志模块实现日志信息的打印和记录,而 Python 提供了内置的日志模块 logging,有必要深入…

解决每次打开pycharm都特别慢的几个方法

Python编写时,通常都会用vscode和pycharm两个工具,使用过程中,发现每次打开pycharm都特别特别慢,有时候要等十来分钟。相信大家可能都有遇到一样的情况,所以分享我自己的解决方法给大家参考。 1,每次需要关…

[附源码]java毕业设计置地房屋租赁信息系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

嵌入式驱动初级-中断

文章目录前言一、Linux 中断 API 函数二、Linux 中断实现三、中断上半部与下半部四、下半部机制之tasklet ---- 基于软中断五、按键中断下半部机制之tasklet六、下半部机制之workqueue ----- 基于内核线程七、按键中断下半部机制之workqueue前言 记录嵌入式驱动学习笔记 一、Li…

一文带你深入理解【Java基础】· 枚举类

写在前面 Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正&#xff0…

Vision Transformer这两年

作者|Maximilian Schambach OneFlow编译 翻译|胡燕君、杨婷 在NLP领域取得巨大成功后,Transformer架构在计算机视觉方面的作用日渐凸显,成为越来越普遍的CV工具。自2020年10月Vision Transformer模型推出以来,人们开始…

《研究生学术与职业素养讲座》第七讲~第九讲作业答案

第七讲 八千里路云和月—2015年意大利米兰世博会中国馆设计 填空题(1分)单选题(1分)判断题(1分)多选题(2分)第八讲 从纳米研究看工程创新 填空题(1分)单…

干货 | 一条语句更新多个表

众所周知,多个服务器命中会减慢应用程序的速度。出于这个原因,开发人员致力于找尋使用最少的语句更新数据的最有效方法。事实证明,SQL UPDATE 语句确实支持使用以下语法设置多个表的字段: UPDATE table1, table2, ...SET column1…

2022-11-14 西安 activiti工作流(01)

语言确实有其局限性,但我相信:一件值得做的事情即使做的不怎么样也是值得的! 概念 1.流程审批以前的实现方式 在没有专门的工作流引擎之前,为了实现流程控制,通常的做法就是采用状态字段的值来跟踪流程的变化情况。通过状态字段的取值来决定…

【数据结构】二叉树优先级队列——堆

文章目录1. 树的概念及结构1.1 树的相关概念1.2 树的表示2. 二叉树的概念及其结构2.1 二叉树的概念2.2 特殊的二叉树2.3 二叉树的性质2.4 二叉树的存储结构3. 堆3.1 堆的概念及结构3.2 堆的实现3.2.1 堆的创建3.2.2 堆的插入3.2.3 堆的向上调整算法3.2.4 堆的删除3.2.5 堆的向下…

javaSE--数据类型(复习)

一、变量和类型 变量 指的是 程序运行时 的 可变的量,相当于开辟一块内存空间来保存一些数据 类型 则是 对 变量的种类 进行了 划分,不同的类型 的 变量 具有不同特性 我们所讨论的"变量"主要 和 我们的"内存"这样的硬件设备密切相关…

value_counts()与count()的简单介绍

文章目录一,value_counts()(一)用法(二)参数介绍二,count()一,value_counts() (一)用法 value_counts()是针对某一列的数据中存在不同的值进行汇总计算 举例 data[dis…

昨天阅读量900

昨天周五了,阅读量还不错的,超过平均值700的,一看有900多呢

80211 TIM流量指示图 附C语言实现

TIM是什么? TIM:Traffic Indication Map,流量指示图。 在80211协议节能模式中,AP会缓存下行数据,AP就是通过beacon帧中TIM来告知休眠中的STA有数据需要接收。 DTIM:Delivery Traffic Indication Map&#…

css引入其它字体

1、下载需要的字体,放到下图的文件夹中。 2、把下载的字体文件放到项目的font目录下 3、在css中加入下面的代码 font-face {font-family: "思源黑体";src: url("../font/SourceHanSansCN-Normal.ttf"); } * { font-family: "思源黑体&quo…

【计算机网络】Cookie、Session和上传文件重点知识汇总

目录 1.Cookie基础知识: 2.Session基础知识: 3.相关API: 3.1.HttpServletRequest类: 3.2.HttpServletResponse类: 3.3.HttpSession类: 3.4.Cookie类: 3.5.模拟实现登录页面 4.上传文件…

伸展树原理介绍

一 点睛 伸展树,也叫作分裂树,是一种二叉搜索树,可以在 O (logn ) 内完成插入、查找和删除操作。在任意数据结构的生命周期内执行不同操作的概率往往极不均衡,而且各操作之间有极强的相关性,在整体上多呈现极强的规律…

【LeetCode】882. 细分图中的可到达节点

题目描述 给你一个无向图(原始图),图中有 n 个节点,编号从 0 到 n - 1 。你决定将图中的每条边 细分 为一条节点链,每条边之间的新节点数各不相同。 图用由边组成的二维数组 edges 表示,其中 edges[i] [ui…

ESG,TO B长期主义里的「新战役」

中国企业最好的方式是从初始阶段就植入ESG基因,使它逐渐从隐形变成显性基因。长期坚持此类发展导向,对后续发展ESG战略,提升ESG合规能力也将成为一种积累和准备。 作者|三七 编辑|皮爷 出品|产业家 20世纪初期,伦敦得到一个延…