3、设计模式之工厂模式2(Factory)

一、什么是工厂模式
工厂模式属于创建型设计模式,它用于解耦对象的创建和使用。通常情况下,我们创建对象时需要使用new操作符,但是使用new操作符创建对象会使代码具有耦合性。工厂模式通过提供一个公共的接口,使得我们可以在不暴露对象创建逻辑的情况下创建对象。

二、工厂分类
工厂模式分为三种类型:简单工厂、方法工厂和抽象工厂,其本质就是对获取对象过程的抽象。

三、应用场景
3.1 生活场景
你需要一辆汽车,可以直接从工厂里提货,而不用关心它具体是怎么实现的
Hibernate换数据库只需要换方言和驱动就可以
3.2 java场景

BeanFactory:它是Spring
IoC容器的核心接口,通过读取配置文件或注解来创建Bean实例,并将它们注入到其他对象中。BeanFactory使用了工厂模式来隐藏具体的对象实例化过程,客户端只需要通过接口获取Bean对象,而不需要关心具体的实例化细节。
FactoryBean:是一种更高级别的工厂模式实现,用于创建特定类型的Bean对象。与普通的BeanFactory不同,FactoryBean的getObject()方法可以返回任意类型的对象实例,并且可以通过配置方式创建和管理实例。
Executors:提供了一系列的工厂方法来创建线程池(ThreadPoolExecutor)及其相关组件。
Charset:提供了一系列的静态工厂方法,如forName()、availableCharsets()等,用于创建Charset实例。

在这里插入图片描述
4.1 传统模式
在介绍工厂模式之前先来看看传统模式,以卖包子为例,如下:

 //简单的制作流程
public BaoZi createBaoZi() {
     BaoZi baozi = new BaoZiImpl();
     //准备材料
     baozi.prepare();
     //制作包子
     baozi.make();
     //蒸包子
     baozi.braise();
     return baozi;
}

包子肯定有很多种类吧,那我们可以直接在上述代码中添加根据包子的种类生成不同类型的对象

/**
* 包子肯定有不同的馅:酸菜、豆沙、猪肉,那么他的材料、售价等方式也不同
* 我们可以直接在上述代码中,添加根据包子的不同种类生成不同的对象。
*/
public BaoZi createBaoZi(String type) {
     BaoZi baoZi = null;
     switch (type){
          case "suancai":
              baoZi=new SuanCaiBaoZi();
              break;
          case "dousha":
              baoZi=new DouShaBaoZi();
              break;
          case "pork":
                baoZi=new PorkBaoZi();
                break;
          default:
              throw new IllegalArgumentException("Invalid BaoZi Type");
      }
      //准备材料
      baoZi.prepare();
      //制作包子
      baoZi.make();
      //蒸包子
      baoZi.braise();
      return baoZi;
}

Test:

  //1.传统模式
    @Test
    void traditonal(){
        SaleBaoZi saleBaoZi=new SaleBaoZi();
        //以猪肉包为例
        saleBaoZi.createBaoZi("pork");
    }

4.2 简单工厂模式
简单工程根据客户端的需求创建具体的实例,这种模式对调用者隐藏了实例创建的过程,也使得创建过程更加容易维护。

还是以卖包子为例,简单工厂模式实现如下:


/**
 * 2.简单工厂方法:希望能够创建一个对象,但创建过程比较复杂,希望对外隐藏这些细节
 */
public class SimpleFactory {
 
    public static BaoZi createBaoZi(String type){
 
        BaoZi baoZi=null;
        switch (type){
            case "suancai":
                baoZi=new SuanCaiBaoZi("酸菜包");
                break;
            case "dousha":
                baoZi=new DouShaBaoZi("豆沙包");
                break;
            case "pork":
                baoZi=new PorkBaoZi("猪肉包");
            case "beef":
                //老板拓展业务了,新加了一个牛肉包类型的包子,那对于简单工厂模式而言,
                //于是就得修改源代码,那么就违反了ocp原则,假如新增100个?
                baoZi=new BeefBaoZi("牛肉包");
                break;
            default:
                throw new IllegalArgumentException("Invalid BaoZi Type");
        }
 
        return baoZi;
    }
}

Test:

  //2.简单工厂模式
    @Test
    void simpleFactory(){
        //以猪肉包为例
        BaoZi pork = SimpleFactory.createBaoZi("pork");
        pork.prepare();
        pork.make();
        pork.braise();
    }

相比传统模式,从类图上就可以看出来,在sale和baozi中间又加了一层。

通过封装SimpleFactory这个类,我们将sale和baozi进行了解耦合。
4.3 方法工厂模式
简单工厂模式下,如果老板拓展业务了,加了一个牛肉种类的包子,就得在源码基础上修改,那么这就违背了开闭原则(ocp),即对扩展开放,对修改关闭。于是,为了解决这个问题,就又了工厂方法模式。

工厂方法模式是一种更加抽象的工厂模式,它将工厂的职责抽象为接口,由具体的工厂实现创建具体的对象。工厂方法模式弱化了工厂的实现,使得每个工厂只负责一个产品的创建。

抽象工厂MeAbStractFactory:

public interface MeAbstractFactory {
    BaoZi createBaoZi();
}

DouShaFactory:

//豆沙包
public class DouShaFactory implements MeAbstractFactory {
    @Override
    public BaoZi createBaoZi() {
        return new DouShaBaoZi("豆沙包");
    }
}

PorkFactory:

//猪肉包
public class PorkFactory implements MeAbstractFactory {
    @Override
    public BaoZi createBaoZi() {
        return new PorkBaoZi("猪肉包");
    }
}

BeefFactory:

//牛肉包
public class BeefFactory implements MeAbstractFactory {
    @Override
    public BaoZi createBaoZi() {
        return new BeefBaoZi("牛肉包");
    }

Test:

  //3.方法工厂模式
    @Test
    void methodFactory(){
        MeAbstractFactory factory=new PorkFactory();
        BaoZi pork = factory.createBaoZi();
        pork.prepare();
        pork.make();
        pork.braise();
    }

之前的SimpleFactory在createBaoZi中直接就new出来了,但在方法工厂中,我们将createBaoZi这个动作推迟到了MeAbStactFactory的子类(XXFactory)中才完成。

好处就是,比如后期要卖个羊肉包,我们直接编写个羊肉包类,然后实现MeAbstractFactory类就,实现它自己的功能,这样完全不用修改原来的代码了,也就解决了违反OCP原则的问题。

4.4 抽象工厂模式
抽象工厂模式是基于工厂方法模式的基础上进行的。在这种模式中,每一个工厂不再只负责一个产品的创建,而是负责一组产品的创建。抽象工厂模式将每个产品组都提取为一个接口,每个工厂都负责一个产品组。

     假如老板的生意做大了,在北京开了个分店,并且不止卖包子,还卖蛋糕,那么该怎么拓展呢,很简单,只需要在抽象工厂类中新增创建蛋糕的抽象方法就行,如下:
AbstractFactorypublic interface AbstractFactory {
    //制作包子
    BaoZi createBaoZi(String type);
    //制作蛋糕
    Cake createCake(String type);
}

BJFactory:

//北京分店
public class BJFactory implements AbstractFactory{
    @Override
    public BaoZi createBaoZi(String type) {
        BaoZi baoZi=null;
        switch (type){
            case "beef":
                baoZi=new BJBeefBao("北京牛肉包");
                break;
            case "pork":
                baoZi=new BJPorkBao("北京猪肉包");
            default:
                break;
        }
        return baoZi;
    }
 
    @Override
    public Cake createCake(String type) {
        Cake cake=null;
        switch (type){
            case "apple":
                cake=new BJAppleCake("北京苹果蛋糕");
                break;
            case "pear":
                cake=new BJPearCake("北京梨味蛋糕");
            default:
                break;
        }
        return cake;
    }
}

Test:

//4.抽象工厂模式
@Test
void abstractFactory(){
    AbstractFactory factory=new BJFactory();
    Cake apple = factory.createCake("apple");
    BaoZi pork = factory.createBaoZi("pork");
 
    apple.prepare();
    apple.make();
    apple.bake();
    apple.sale();
 
    pork.prepare();
    pork.make();
    pork.braise();
    pork.sale();
}

5.1 简单工厂模式

优点:

简单工厂模式实现简单,易于理解和使用; 可以对对象的创建进行集中管理,客户端和具体实现解耦。
缺点:

工厂类负责创建所有对象,如果需要添加新类型的产品,则需要修改工厂类的代码,这违反了开闭原则; 工厂类职责过重,导致单一职责原则被破坏。
适用场景:

工厂类负责创建的对象较少,客户端不需要知道对象的创建过程; 客户端需要根据传递的参数来获取对应的对象。

5.2 方法工厂模式

优点:

方法工厂模式具有良好的可扩展性,如果需要添加新类型的产品,只需要添加对应的工厂方法即可;
与简单工厂模式相比,方法工厂模式更符合开闭原则和单一职责原则。
缺点:

需要客户端自行选择使用哪个工厂方法,不能像简单工厂模式那样直接传参获取对应对象,因此对客户端的编写有一定要求。 适用场景:

应用中需要创建的对象较少,但是需要具备良好的可扩展性; 客户端可以自行选择创建哪种对象。

5.3 抽象工厂

优点:

抽象工厂模式可以创建多个产品族的产品,这些产品之间有相互依赖或约束关系,有助于保持系统的一致性和稳定性;
客户端与具体产品解耦,通过产品族的方式进行管理。
缺点:

抽象工厂模式增加了系统的抽象性和理解难度,不易于理解和修改; 新增产品族时需要修改工厂接口、工厂实现类和产品类,增加了系统的复杂性。
适用场景:

系统需要一系列相互依赖或约束的产品; 客户端不需要知道具体产品的创建过程,只需要知道产品族即可。

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

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

相关文章

TS271IDT运算放大器芯片中文资料PDF数据手册引脚图图片参数价格功能

产品描述: TS271 是一款低成本、低功耗的单通道运算放大器,设计用于采用单电源或双电源供电。该运算放大器采用意法半导体硅栅CMOS工艺,具有出色的消耗-速度比。该放大器非常适合低功耗应用。 电源可通过引脚 8 和 4 之间连接的电阻器进行外…

Linux:深入文件系统

一、Inode 我们使用ls -l的时候看到的除了看到文件名,还看到了文件元数据。 [rootlocalhost linux]# ls -l 总用量 12 -rwxr-xr-x. 1 root root 7438 "9月 13 14:56" a.out -rw-r--r--. 1 root root 654 "9月 13 14:56" test.c 每行包含7列&…

Win11系统启动VMware上虚拟机蓝屏解决办法

背景 最近有在做一个项目的过程中需要使用虚拟机,用原来装好的的Vmware14打开虚拟机,直接蓝屏了,尝试了如下几种方法来解决,最好用的就是第二种,直接下载最新版本(在软件管家中直接下载)。 虚拟机 目前常用的虚拟机软…

idea+maven+tomcat+spring 创建一个jsp项目

概述:我真服了,这个垃圾学校还在教jsp,这种技术我虽然早会了,但是之前搞的大多都是springboot web类型的,这里我就复习一下,避免以后忘记这种垃圾技术 第一步:创建maven项目 第二步&#xff1a…

Java设计模式:桥接模式

❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得关注、点赞、收藏、…

【STL】deque双端开口容器

1.关于deque容器说明 deque容器与vector容器差不多,但deque是双端开口容器,可以在两端插入和删除元素 push_front( )//在头部插入 push_back( )//在尾部插入 pop_front( )//在头部删除 pop_back( ) //在尾部删除 其他相应函数与vector差不多&#…

Pytorch入门-TensorBoard

文章目录 WhatHOWSummaryWriter What TensorBoard是TensorFlow自带的一个强大的可视化工具,也是一个Web应用程序套件。 torch.utils.tensorboard 是 PyTorch 提供的一个用于将标量、图像、直方图和其他信息记录到 TensorBoard 中的实用程序包。TensorBoard 是 Tenso…

Pycharm的Project Structure (项目结构)

文章目录 一、Sources二、Tests三、Exeluded四、Namespace packages五、Templates六、Resources 一、Sources 源代码根目录:包含项目的主要源代码,它会在这个目录下搜索代码,然后自动补全和只能提示都通过这里的代码提供。若项目运行自定义代…

rabbitmq-spring-boot-start配置使用手册

rabbitmq-spring-boot-start配置使用手册 文章目录 1.yaml配置如下2.引入pom依赖如下2.1 引入项目resources下libs中的jar包依赖如下2.2引入maven私服依赖如下 3.启动类配置如下4.项目中测试发送消息如下5.项目中消费消息代码示例6.mq管理后台交换机队列创建及路由绑定关系如下…

Java算法总结之冒泡排序(详解)

程序代码园发文地址:Java算法总结之冒泡排序(详解)-程序代码园小说,Java,HTML,Java小工具,程序代码园,http://www.byqws.com/ ,Java算法总结之冒泡排序(详解)http://www.byqws.com/blog/3145.html?sourcecsdn 冒泡排序…

(day 7)JavaScript学习笔记(函数1)

概述 这是我的学习笔记,记录了JavaScript的学习过程,我是有一些Python基础的,因此在学习的过程中不自觉的把JavaScript的代码跟Python代码做对比,以便加深印象。在写博客的时候我会尽量详尽的记录每个知识点。如果你完全没接触过J…

社媒营销会遇到的封号问题

最近看到很多的直播都在教伙伴们怎么用linked in 以及facebook开发客户,比如如何添加联系人,如何用添加好友的话术,如何加群,如何分析客户的背景等等。 有的主播只是讲一些表面的东西,有的主播可能是真的肚子里有货&a…

【DataWhale学习】用免费GPU线上跑StableDiffusion项目实践

用免费GPU线上跑SD项目实践 ​ DataWhale组织了一个线上白嫖GPU跑chatGLM与SD的项目活动,我很感兴趣就参加啦。之前就对chatGLM有所耳闻,是去年清华联合发布的开源大语言模型,可以用来打造个人知识库什么的,一直没有尝试。而SD我…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:StepperItem)

用作Stepper组件的页面子组件。 说明: 该组件从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 支持单个子组件。 接口 StepperItem() 属性 参数名参数类型参数描述prevLabelstring设置左侧文本按钮内…

硬件软件_驱动程序只有cat,inf,sys,怎么安装?

硬件软件_驱动程序只有cat,inf,sys,怎么安装? 右键点击inf文件 -》 安装 即可完成。

文件外发管理软件(控制文件外发的软件·精选推荐)

无论是与合作伙伴共享资料、还是员工需要在家办公时访问公司内部文件,文件的外发都是必要的。然而,这也带来了数据泄露的风险。 如果没有有效的管理手段,敏感信息可能会被未授权的人员获取,进而对企业的商业机密、客户隐私和知识…

Excel查找函数的高级用法

查找在实际工作中是经常遇到的,那你会查找吗?本期与大家分享6个查找函数技巧。 一、查找的基础用法 1、根据内容查找相应的行数 想知道数据在区域中的位置,可以用MATCH函数。 举个例子,查找“刘冰”在姓名列中所在的函数。 输…

Web-based DBMS Technology 线上数据库

Example Online Databases • https://www.planespotters.net/ • https://www.comics.org/ • https://www.quandl.com/ • https://www.enigma.com/ • https://www.sportradar.com/ Basics of WWW • The Web is a very large client-server system — Connected through r…

Anaconda的使用及spyder相关设置

Anaconda Anaconda是一个Python发行版,主要用于数据科学和机器学习领域。Anaconda集成了许多常用的数据科学工具和库,如NumPy、Pandas、Scikit-learn等,同时还包含了一个强大的包管理器conda和一个集成开发环境Spyder。Anaconda的目标是提供一…

电脑回收站图标更改

小猫图标 效果图 1.下载压缩包 https://www.123pan.com/s/9QRqVv-u3lY.html 解压后得到两个文件 coo.dll(满) ooo.dll(空)把这两个文件放到C盘的图片文件夹中 2.更改图标 wini打开设置,选择个性化&#xff0c…