简单工厂、工厂方法、抽象工厂模式-这仨货的区别

news2024/12/23 18:45:49

7a744a67c16180849308456cf88fc0f6.jpeg

要想明白这三玩意的区别就需要知道这三玩意的优缺点;

之所以有三种工厂模式,就说明它们各有所长,能解决不同场景的问题;

一、简单工厂模式

UML图

d4947efe7f5e040ce42be86425338136.png

代码

public class MobileFactory {
    public static Mobile getMobile(String brand){
        switch (brand){
            case "apple":
                return new AppleMobile();
            case "huawei":
                return new HuaweiMobile();
            default: throw new RuntimeException("参数不合法");
        }
    }
}


public interface Mobile {
    String getBrand();
}
public class AppleMobile implements Mobile {
    @Override
    public String getBrand() {
        return "apple";
    }
}
public class HuaweiMobile implements Mobile {
    @Override
    public String getBrand() {
        return "huawei";
    }
}


public class Client {
    public static void main(String[] args) {
        Mobile appleMobile = MobileFactory.getMobile("apple");
        System.out.println(appleMobile.getBrand());
        Mobile huaweiMobile = MobileFactory.getMobile("huawei");
        System.out.println(huaweiMobile.getBrand());
    }
}


//如果想增加小米手机的生产,则需要修改 Factory类的代码:public class MobileFactory {
    public static Mobile getMobile(String brand){
        switch (brand){
            case "apple":
                return new AppleMobile();
            case "huawei":
                return new HuaweiMobile();
            case "xiaomi":
                return new XiaomiMobile();
            default: throw new RuntimeException("参数不合法");
        }
    }
}

优点

不需要定义工厂接口,往往直接写一个工厂实现类,方法往往也是静态的,客户端用起来非常方便快捷。

缺点

不符合开闭原则,增加产品种类时需要修改工厂类代码(if else问题),为了解决此缺点,工厂方法模式产生

二、工厂方法模式

UML图

e94816d4dc786603190ddceef56b1a28.png

代码

//只生产一种产品,生产不同的产品需要不同的工厂
public class Client {
    public static void main(String[] args) {
        IFactory factory;
        IProduct product;
        
        //华为工厂 生产华为播放器
        factory = new FactoryHuawei();
        product = factory.getProduct();
        product.sing();


        //小米工厂 生产小米播放器
        factory = new FactoryXiaomi();
        product = factory.getProduct();
        product.sing();
    }
}


public interface IFactory {
    IProduct getProduct();
}
public interface IProduct {
    /**
     * 这个产品可以唱歌
     */
    void sing();
}
public class FactoryHuawei implements IFactory {
    @Override
    public IProduct getProduct() {
        return new ProductHuawei();
    }
}
public class FactoryXiaomi implements IFactory {
    @Override
    public IProduct getProduct() {
        return new ProductXiaomi();
    }
}
public class ProductHuawei implements IProduct {
    @Override
    public void sing() {
        System.out.println("hi,我是华为音乐播放器,我正在唱歌。。。。。");
    }
}
public class ProductXiaomi implements IProduct {
    @Override
    public void sing() {
        System.out.println("hi,我是小米音乐播放器,我正在唱歌。。。。。");
    }
}

优点

解决了简单工厂模式违反“开闭原则”的问题,增加产品的种类不需要修改已有代码。直接实现一个工厂接口即可。

缺点

在生产多种商品的情况下,工厂接口和实现类的数量会大大增加。但是每个工厂目前只有一个车间只能生产一种产品,老板不服,因为他觉得一个工厂只有一个车间太浪费了,我要在一个工厂里开多个车间生产不同的产品

三、抽象工厂模式

UML图

a2246f02bca769bbbe80efbc377e3163.png

代码

//用于一个系列或风格的产品生成
public class Client {


    public static void main(String[] args) {
        System.out.println("来一套A牌茶具");
        FactoryTeaset teasetA = new FactoryTeasetA();
        Tea teaA = teasetA.getTea();
        Teacup teacupA = teasetA.getTeacup();
        Teapot teapotA = teasetA.getTeapot();
        teaA.show();
        teacupA.show();
        teapotA.show();


        System.out.println("来一套B牌茶具");
        FactoryTeaset teasetB = new FactoryTeasetB();
        Tea teaB = teasetB.getTea();
        Teacup teacupB = teasetB.getTeacup();
        Teapot teapotB = teasetB.getTeapot();
        teaB.show();
        teacupB.show();
        teapotB.show();
    }
}
public interface FactoryTeaset {
    //生产茶壶
    Teapot getTeapot();
    //生产茶杯
    Teacup getTeacup();
    //生产茶叶
    Tea getTea();
}
public interface Tea {
    void show();
}
public interface Teacup {
    void show();
}
public interface Teapot {
    void show();
}


//A品牌茶具工厂
public class FactoryTeasetA implements FactoryTeaset {
    @Override
    public Teapot getTeapot() {
        return new TeapotA();
    }
    @Override
    public Teacup getTeacup() {
        return new TeacupA();
    }
    @Override
    public Tea getTea() {
        return new TeaA();
    }
}
public class TeaA implements Tea {
    @Override
    public void show() {
        System.out.println("我是A牌茶叶");
    }
}
public class TeacupA implements Teacup {
    @Override
    public void show() {
        System.out.println("我是A牌茶杯");
    }
}
public class TeapotA implements Teapot {
    @Override
    public void show() {
        System.out.println("我是A牌茶壶");
    }
}


//B品牌茶具工厂
public class FactoryTeasetB implements FactoryTeaset {
    @Override
    public Teapot getTeapot() {
        return new TeapotB();
    }
    @Override
    public Teacup getTeacup() {
        return new TeacupB();
    }
    @Override
    public Tea getTea() {
        return new TeaB();
    }
}
public class TeaB implements Tea {
    @Override
    public void show() {
        System.out.println("我是B牌茶叶");
    }
}
public class TeacupB implements Teacup {
    @Override
    public void show() {
        System.out.println("我是B牌茶杯");
    }
}
public class TeapotB implements Teapot {
    @Override
    public void show() {
        System.out.println("我是B牌茶壶");
    }
}

优点

解决了类爆炸问题,一个工厂有多个车间,可以生产一套产品、一个系列产品,并且这些产品品牌一致、风格一致、看着高大上。从来不会由于失误把A品牌的茶杯和B品牌的茶壶组合在一起使用。

缺点

一天老板想增加“茶桌”生产线,需要在厂里增加一个生产车间,好在它并不需要修改其它车间,只需要增加一个新的车间。其它茶具老板一听说行业规范变了,竞争对手已经增加了“茶桌”,他也必须跟上,否则就落伍了,不符合行业规范可是会被取缔啊。

四、总结

1、简单工厂不需要工厂接口,工厂类往往提供静态方法,简单方便。但是存在不断增加if else问题,不符合开闭原则。

2、工厂方法模式完全符合开闭原则,但会产生大量的接口和实现类,俗称“类爆炸”

3、抽象工厂模式不会产生大量的接口和实现类,但是在扩展性上又不完全符合开闭原则,但不会存在if else问题。

4、所以老吕认为:抽象工厂模式解决了“简单工厂模式”的if else问题,同时解决了 “工厂方法模式”的类爆炸问题,但在开闭原则上有一定的损害,这可能就是“折中”的意义吧,世界上本没有完美的方案,实际使用中还是要根据业务场景、团队情况等综合判断来决定使用哪种模式,并不是越复杂越好也不是越完美越好。

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

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

相关文章

【Linux】线程概述、创建线程、终止线程

目录 线程概述1、创建线程函数解析代码举例 2、终止线程函数解析代码举例 橙色 线程概述 与进程类似,线程是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。 进程是 CPU 分配资源的最小单位,线程是操作系统调度执行的最小单位。…

回归预测 | MATLAB实现SSA-CNN-LSTM麻雀算法优化卷积长短期记忆神经网络多输入单输出回归预测

回归预测 | MATLAB实现SSA-CNN-LSTM麻雀算法优化卷积长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现SSA-CNN-LSTM麻雀算法优化卷积长短期记忆神经网络多输入单输出回归预测预测效果基本介绍模型描述程序设计学习总结参考资料 预测效果 基本介绍 MATLAB实现…

【笔记整理】轻量级神经网络 MobileNetV3

【笔记整理】轻量级神经网络 MobileNetV3 文章目录 【笔记整理】轻量级神经网络 MobileNetV31、深度可分离卷积2、翻转残差块和线性瓶颈结构3、h-swish 函数和 SE 模块4、网络结构搜索 近年来关于 CNN 的研究在飞速发展,CNN 模型在目标检测、图像分割等领域都取得了…

力扣sql中等篇练习(二十九)

力扣sql中等篇练习(二十九) 1 计算每个销售人员的影响力 1.1 题目内容 1.1.1 基本题目信息1 1.1.2 基本题目信息2 1.1.3 示例输入输出 a 示例输入 b 示例输出 1.2 示例sql语句 # Write your MySQL query statement below SELECT s1.salesperson_id,s1.name,IFNULL(t.total…

毕业季到底是去大厂还是去小公司

(点击即可收听) 毕业季到底是去大厂还是去小公司 相信很多人在选择大小公司的时候,会比较痛苦,外面的人想进去,里面的人想出来,至于选择大厂还是小公司 这是因人而异的,不同的阶段都可以有不同的选择 进大厂不一定就是对的,进小公司也不一定就是错的,学习东西,增长经…

股票量化分析工具QTYX使用攻略——涨停个股挖掘热门板块(更新2.6.5)

搭建自己的量化系统 如果要长期在市场中立于不败之地!必须要形成一套自己的交易系统。 行情不等人!边学习边实战,在实战中学习才是最有效地方式。于是我们分享一个即可以用于学习,也可以用于实战炒股分析的量化系统——QTYX。 QTY…

软考A计划-试题模拟含答案解析-卷九

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…

JetBrains的多数据库管理和SQL工具DataGrip 2023版本在Win10系统的下载与安装配置教程

目录 前言一、DataGrip 安装二、使用配置总结 前言 DataGrip是一款多数据库管理和SQL工具,适用于不同类型的数据库。它提供了丰富的功能和工具,可以帮助开发人员更高效地管理数据库、编写SQL查询和执行数据操作。 DataGrip的主要特点: ——…

这里有3个Tips,也许可以帮你躲过ChatGPT大规模封号 | AIGC实践

据说,从昨天开始,ChatGPT又双叒叕开始大规模封号,很多注册用户收到这样一则消息: 大意是说:OpenAI 发现了你的 ChatGPT 账号存在可疑活动,为了保障平台安全,已自动退款并取消你的 ChatGPT Plus …

驱动开发:内核解析内存四级页表

当今操作系统普遍采用64位架构,CPU最大寻址能力虽然达到了64位,但其实仅仅只是用到了48位进行寻址,其内存管理采用了9-9-9-9-12的分页模式,9-9-9-9-12分页表示物理地址拥有四级页表,微软将这四级依次命名为PXE、PPE、P…

七年老程序员的三四月总结:三十岁、准备婚礼、三次分享

你好,我是 shixin,一名工作七年的安卓开发。 每两个月我会做一次总结,记下这段时间里有意义的事和值得反复看的内容,为的是留一些回忆、评估自己的行为、沉淀有价值的信息。 一转眼 2023 年过去了三分之一,这两个月经历…

【数据湖仓架构】数据湖和仓库:Databricks 和 Snowflake

是时候将数据分析迁移到云端了。我们比较了 Databricks 和 Snowflake,以评估基于数据湖和基于数据仓库的解决方案之间的差异。 在这篇文章中,我们将介绍基于数据仓库和基于数据湖的云大数据解决方案之间的区别。我们通过比较多种云环境中可用的两种流行技…

HTML+CSS+JavaScript制作弹幕效果

全屏弹幕 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>弹幕效果</title><style>/* 设置弹幕的样式 */.bullet {position: absolute;font-size: 20px;color: white;text-shadow: 1px 1px 1px black;white-s…

用Python让小朋友的手绘图跳起来(附源码)

大家好&#xff0c;我是小F&#xff5e; 今天给大家介绍一个非常有趣的项目&#xff0c;基于AI识别&#xff0c;制作儿童手绘图舞蹈图。 只需几分钟&#xff0c;就能自动生成儿童手绘人物或类人角色&#xff08;即具有双臂、两条腿等的角色&#xff09;的动画&#xff0c;而且生…

波奇学C++:模板和STL

什么是模板&#xff1f;为什么我们需要模板&#xff1f; 先假设一个场景&#xff0c;我们要编写一个函数交换a,b两个数的值 void swap(int& a,int& b) {int cmpa;ab;ba; } swap函数可以帮我们交换两个int型的值&#xff0c;那如果要交换的类型是float&#xff0c;do…

基础篇010.1 STM32驱动RC522 RFID模块之一:基础知识

目录 1. RFID概述 1.1 RFID工作原理 1.2 RFID分类 1.3 RFID模块 1.4 RFID卡片 1.5 IC卡和ID卡介绍 1.6 IC卡和ID的区分 2. Mifare卡结构原理 2.1 Mifare卡概述 2.2 Mifare非接触式 IC 卡性能简介&#xff08;M1&#xff09; 2.2.1 Mifare S50与Mifare S70 2.2.2 S5…

操作系统的发展史

█ DOS操作系统 上期提到&#xff0c;20世纪70年代&#xff0c;伴随着计算机技术的成熟&#xff0c;操作系统也进入了一个快速发展阶段。现代操作系统的概念&#xff0c;也在那一时期逐渐形成。 1975年初&#xff0c;MITS电脑公司推出了基于Intel 8080芯片的Altair 8800微型计算…

7 种常见的路由协议

网络路由是网络通信的重要组成部分&#xff0c;通过互联网将信息从源地址移动到目的地的过程。路由发生在 OSI 模型的第 3 层&#xff08;网络层&#xff09;。实际网络中通常会将静态和动态路由结合使用。静态路由适用于小型网络&#xff0c;而动态路由适用于大型网络。 什么…

Office project 2013安装

哈喽&#xff0c;大家好。今天一起学习的是project 2013的安装&#xff0c;Microsoft Office project项目管理工具软件&#xff0c;凝集了许多成熟的项目管理现代理论和方法&#xff0c;可以帮助项目管理者实现时间、资源、成本计划、控制。有兴趣的小伙伴也可以来一起试试手。…

Anthropic 推出 Claude ,一款与ChatGPT竞争的聊天机器人

最近&#xff0c;谷歌承诺向 Anthropic 投资 3 亿美元&#xff0c;收购这家初创公司 10% 的股份。 Anthropic 是一家由前 OpenAI 员工共同创立的初创公司&#xff0c;近日推出一款与ChatGPT对标的产品。 Anthropic 名为 Claude 的人工智能聊天机器人&#xff0c;可以被指示执行…