设计模式04-创建型模式1(简单工厂/工厂模式/抽象工厂/Java)

3.1 简单工厂模式

3.1.1 创建型模式

创建型设计模式将对象的创建过程和对象的使用过程分离,用户使用对象时无需关注对象的创建细节,外界对于这些对象只需要知道它们共同的接口,而不用清楚其实现细节,使得整个系统的设计更加符合单一职责原则。软件的结构也更为清晰。

3.1.2 简单工厂模式的定义

专门定义一个类来负责创建其他类的实例,可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

3.1.3 简单工厂模式的分析与实现
image-20241018173701097
  • 工厂角色:即工厂类,简单工厂模式的核心,负责实现创建所有实例的内部逻辑;工厂类可被外部直接调用,创建所需的产品对象;工厂类中提供了静态的工厂方法(它返回一个抽象产品类Product,所有具体产品都是抽象产品的子类。

  • 工厂类中只有简单的逻辑判断代码。不关心具体的业务处理过程,满足“单一职责原则”。

  • 调用工厂类的工厂方法时,由于工厂方法时静态方法,使用很方便,可通过类名直接调用,只需要传入一个简单的参数即可。

3.1.4 简单工厂模式的案例

某电视机厂专为各知名电视机品牌代工生产各类电视机,当需要海尔牌电视机时只需要在调用该工厂的工厂方法时传入参数“Haier”,需要海信电视机时只需要传入参数“Hisense”,工厂可以根据传入的不同参数返回不同品牌的电视机。现使用简单工厂模式来模拟该电视机工厂的生产过程。

image-20241018174238661
  • 抽象产品类和具体产品类
public interface TV {
    public void play();
}

public class HaierTV implements TV{
    @Override
    public void play() {
        System.out.println("Haier电视正在播放");
    }
}

public class HisenseTV implements TV{
    @Override
    public void play() {
        System.out.println("hisense电视正在播放");
    }
}
  • 工厂类
public class TVFactory {
    public static TV getTVMethod(String flag) throws Exception {
        if ("Haier".equalsIgnoreCase(flag)) {
            return new HaierTV();
        } else if ("Hisense".equalsIgnoreCase(flag)) {
            return new HisenseTV();
        } else {
            throw new Exception("抱歉没有此类电视");
        }
    }

  • Main类
public class Main {
    public static void main(String[] args) {
        String tvName = XMLUtilTV.getTVName();
        try {
            TV tvMethod = TVFactory.getTVMethod(tvName);
            tvMethod.play();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

public class XMLUtilTV {
    public static String getTVName() {
        try {
            //创建文本对象
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document document = db.parse(new File("src/main/resources/TVBrand.xml"));

            //通过DOM获取文本元素
            NodeList brandName = document.getElementsByTagName("brandName");
            Node content = brandName.item(0).getFirstChild();
            return content.getNodeValue();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

<?xml version="1.0" encoding="ISO-8859-1"?>
<config>
    <brandName>Hisense</brandName>
</config>
3.1.5 简单工厂模式的优缺点
优点缺点
1.实现了对象的创建和使用分离1.工厂类职责太重,不宜维护
2.无需知道类名,只需要知道参数2.系统扩展难度大,且工厂类为静态类不能进行扩展
3.1.6 简单工厂模式适用场景
  • 工厂类负责创建的对象比较少,由于创建对象比较少。
  • 客户端只知道传入工厂类的参数,对于如何创建对象不关心。

3.2 工厂模式

3.2.1 工厂模式的定义

动机:为了解决简单工厂模式不易扩展以及工厂类职责太重的为问题。

在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口, 而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定 究竟应该实例化哪一个具体产品类。

3.2.2 工厂模式的分析与实现
image-20241018180159172
  • 核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给其子类去完成

  • 可以允许系统在不修改工厂角色的情况下引进新产品,增加具体产品–>增加具体工厂,符合“开闭原则”。

3.2.3 工厂模式的案例

将原有的电视机工厂进行分割,为每种品牌的电视机提 供一个子工厂,海尔工厂专门负责生产海尔电视机,海 信工厂专门负责生产海信电视机,如果需要生产TCL电视 机或创维电视机,只需要对应增加一个新的TCL工厂或创 维工厂即可,原有的工厂无须做任何修改,使得整个系 统具有更加的灵活性和可扩展性。

image-20241018180604353
  • 产品类
public interface TV {
    public void play();
}
public class HaierTV implements TV{
    @Override
    public void play() {
        System.out.println("Haier电视正在播放");
    }
}
public class HisenseTV implements TV{
    @Override
    public void play() {
        System.out.println("Hisense电视正在播放");
    }
}
  • 工厂类
public interface TVFactory {
    public TV produceTV();
}
public class HaierTVFactory implements TVFactory{
    @Override
    public TV produceTV() {
        System.out.println("海尔电视已经被制造");
        return new HaierTV();
    }
}
public class HisenseTVFactory implements TVFactory{
    @Override
    public TV produceTV() {
        System.out.println("海信电视已被制造");
        return new HisenseTV();
    }
}
  • 调用(为了更好的满足开闭原则,这里使用Java的反射机制来代替new关键字)
public class XMLUtilTVFactory {
    public static Object getTVFactoryMethod() throws Exception{
        //获取文本对象
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new File("src/main/resources/TVFactoryMethod.xml"));

        //获取文本内容
        NodeList nodeList = doc.getElementsByTagName("factoryName");
        Node firstChild = nodeList.item(0).getFirstChild();
        String nodeValue = firstChild.getNodeValue();

        //通过反射获取对象
        Class className = Class.forName(nodeValue);
        Object obj = className.newInstance();
        return obj;
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            HisenseTVFactory tvFactoryMethod = (HisenseTVFactory) XMLUtilTVFactory.getTVFactoryMethod();
            TV tv = tvFactoryMethod.produceTV();
            tv.play();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

xml:
<?xml version="1.0" encoding="UTF-8" ?>
<config>
    <factoryName>com.tyut.factory_method.example2.HisenseTVFactory</factoryName>
</config>
3.2.4 工厂模式的优缺点
优点缺点
1.实现了对象的创建和使用分离,将对象的创建细节全部封装在工厂中1.系统中的类的个数成对出现,加重系统的负担
2.在系统中添加新产品,完全符合开闭原则
3.2.5 工厂模式的适用场景
  • 客户端不需要知道具体 产品类的类名,只需要知道所对应的工厂即可,具体产品对 象由具体工厂类创建
  • 抽象工厂类通过其子类来指定创建哪个对象

3.3 抽象工厂模式

3.3.1 抽象工厂模式的定义

动机:需要一个工厂,生产多个对象

产品等级结构:产品的继承结构(一个产品的不同表现形式:名词)

产品族:指由同一个工厂生产的,位于不同产品等级结构中的一组产品(形容词)

定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

3.3.2 抽象工厂模式的分析与实现
image-20241018182801135
  • 抽象工厂中定义了多个方法,每一个方法代表一个产品等级
  • 具体工厂即表示每一个产品族的工厂
3.3.3 抽象工厂的案例

一个电器工厂可以产生多种类型的电器,如海尔工厂可以生产海尔电视机、海尔空调等,TCL工厂可以生产TCL电视机、TCL空调等,相同品牌的电器构成一个产品族,而相同类型的电器构成了一个产品等级结构,现使用抽象工厂模式模拟该场景。

image-20241018183128890
  • 产品类
public interface TV {
    public void play();
}
public class HaierTV implements TV{
    @Override
    public void play() {
        System.out.println("海尔电视正在播放");
    }
}
public class HisenseTV implements TV{
    @Override
    public void play() {
        System.out.println("海信电视正在播放");
    }
}

public interface Conditioner {
    public void work();
}
public class HaierConditioner implements Conditioner{
    @Override
    public void work() {
        System.out.println("海尔空调正在工作");
    }
}
public class HisenseConditioner implements Conditioner{
    @Override
    public void work() {
        System.out.println("海信空调正在工作");
    }
}
  • 工厂类
public interface BrandFactory {
    public TV creatTV();
    public Conditioner createConditioner();
}
public class HisenseFactory implements BrandFactory{
    @Override
    public TV creatTV() {
        System.out.println("海信电视已被制作");
        return new HisenseTV();
    }

    @Override
    public Conditioner createConditioner() {
        System.out.println("海信空调已被制作");
        return new HisenseConditioner();
    }
}
public class HaierFactory implements BrandFactory{
    @Override
    public TV creatTV() {
        System.out.println("海尔电视已被制作");
        return new HaierTV();
    }

    @Override
    public Conditioner createConditioner() {
        System.out.println("海尔空调已被制作");
        return new HaierConditioner();
    }
}
  • Main类
public class Main {
    public static void main(String[] args) {
        try {
            BrandFactory factory = (HisenseFactory) XMLUtilBrandFactory.getFactory();
            TV tv = factory.creatTV();
            tv.play();

            Conditioner conditioner = factory.createConditioner();
            conditioner.work();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

public class XMLUtilBrandFactory {
    public static Object getFactory() throws Exception{
        //获取XML文本
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new File("src/main/resources/BrandFactory.xml"));

        //获取工厂名字
        NodeList nodeList = doc.getElementsByTagName("brandFactory");
        Node firstChild = nodeList.item(0).getFirstChild();
        String className = firstChild.getNodeValue();

        //通过反射获取工厂对象
        Class<?> aClass = Class.forName(className);
        Object obj = aClass.newInstance();
        return obj;
    }
}
3.3.4 抽象工厂的优缺点
优点缺点
1.实现了对象的创建和使用分离。1.增加新的产品等级结构麻烦,违背了开闭原则
2.当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象
3.3.5从抽象工厂模式的适用场景
  • 系统中有多于一个的产品族,但每次只使用其中某一产品族
  • 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节

image-20241018184601239

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

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

相关文章

Redis JSON介绍

Redis JSON介绍 Redis JSON先说说JSON是什么再说说JSON Path先推荐两个网站JSONPath JAVA clents Redis JSON 安装内存json命令语法命令url命令解释JSON.ARRAPPENDJSON.ARRINDEXJSON.ARRINSERTJSON.ARRLENJSON.ARRPOPJSON.ARRTRIMJSON.CLEARJSON.DEBUG MEMORYJSON.DEBUGJSON.DE…

单例模式(自动加载)

目录 介绍 使用 在脚本中写一个函数 让一个「自定义场景」作为单例「自动加载」 介绍 单例模式是编程中的一种设计思想&#xff0c;是为了解决某些编程语言中没有全局变量概念而产生的这对于实现某种模块非常好用 比如玩家信息&#xff0c;有时候&#xff0c;游戏中的很多…

数组中超过一半的元素

有一个数组&#xff0c;找出其中数量超过的元素是谁。比如数组 [3, 2, 3] &#xff0c;输出 3。 这个问题要解起来不难&#xff0c;暴力计数&#xff0c;转为 map&#xff0c;排序都能解决。但是他们的空间复杂度都不低&#xff0c;即便排序能做到 O(1) 的空间复杂度&#xff…

计算机系统简介

一、计算机的软硬件概念 1.硬件&#xff1a;计算机的实体&#xff0c;如主机、外设、硬盘、显卡等。 2.软件&#xff1a;由具有各类特殊功能的信息&#xff08;程序&#xff09;组成。 系统软件&#xff1a;用来管理整个计算机系统&#xff0c;如语言处理程序、操作系统、服…

电影评论网站:Spring Boot技术栈应用

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理电影评论网站的相关信息成为必然。开发合适…

安装macOS Sequoia注意事项

随着macOS Sequoia的发布&#xff0c;许多Mac用户开始计划升级到这一最新版本。然而&#xff0c;升级系统并非简单点击“升级”按钮即可。在安装新系统之前&#xff0c;有一些关键的注意事项可以帮助你避免潜在的问题&#xff0c;确保顺利过渡到macOS Sequoia。本文将详细介绍在…

FPGA图像处理之三行缓存

文章目录 一、前言二、FPGA实现三行缓存的架构三、Verilog代码实现四、仿真验证五、输入图像数据进行仿真验证 一、前言 在 FPGA 做图像处理时&#xff0c;行缓存是一个非常重要的一个步骤&#xff0c;因为图像输入还有输出都是一行一行进行的&#xff0c;即处理完一行后再处理…

实现uniapp天地图边界范围覆盖

前言&#xff1a; 在uniapp中&#xff0c;难免会遇到使用地图展示的功能&#xff0c;但是百度谷歌这些收费的显然对于大部分开源节流的开发者是不愿意接受的&#xff0c;所以天地图则是最佳选择。 此篇文章&#xff0c;详细的实现地图展示功能&#xff0c;并且可以自定义容器宽…

Python画笔案例-086 turtle 多线程绘画

1、turtle 多线程绘画 通过 python 的turtle 库 多线程绘画,如下图: 2、实现代码 turtle 库 多线程绘画,以下为实现代码: """多线程绘画.py """ from random import random,randint from turtle import Turtle,Screen from threading

SpringDataRedis快速入门

SpringDataRedis 什么是SpringDataRedis SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis SpringDataRedis中提供了RedsiTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类…

redis基础—主从同步原理与配置以及哨兵模式

一&#xff1a;redis的主从同步原理 1.slave节点发送同步请求到master节点 2.slave节点通过master节点的认证开始进行同步 3.认证结束后&#xff0c;master节点开启bgsave进程 4.master节点会开启bgsave进程发送内存快照rbd到slave节点&#xff0c;在此过程中是异步操作&…

【原创】java+springboot+mysql在线文件管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

Docker学习笔记(2)- Docker的安装

1. Docker的基本组成 镜像&#xff08;image&#xff09;&#xff1a;Docker镜像就像是一个模板&#xff0c;可以通过这个模板来创建容器服务。通过一个镜像可以创建多个容器。最终服务运行或者项目运行就是在容器中。容器&#xff08;container&#xff09;&#xff1a;Docker…

Spring6梳理14——依赖注入之P命名空间

以上笔记来源&#xff1a; 尚硅谷Spring零基础入门到进阶&#xff0c;一套搞定spring6全套视频教程&#xff08;源码级讲解&#xff09;https://www.bilibili.com/video/BV1kR4y1b7Qc 目录 ①搭建模块 ②引入配置文件 ③创建bean-dip.xml文件 ④创建课程类文件 ⑤创建学生…

基于SpringBoot+Vue+uniapp微信小程序的校园反诈骗微信小程序的详细设计和实现(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

day-69 使二进制数组全部等于 1 的最少操作次数 II

思路 与3191. 使二进制数组全部等于 1 的最少操作次数 I思路类似&#xff0c;区别在于该题每次将下标i开始一直到数组末尾所有元素反转&#xff0c;所以我们用一个变量可以统计翻转次数 解题过程 从左向右遍历数组的过程中&#xff0c;有两种情况需要进行翻转&#xff1a;1.当…

【Linux】内存文件系统的I/O、重定向

文章目录 1. 系统中的文件2. 回顾C中的文件接口3. 文件类的系统调用3.1 open3.2 文件描述符 4. IO的基本过程5.重定向5.1 引入重定向5.2 系统中的重定向接口 6. 缓冲区问题7. 简单版shell的实现 1. 系统中的文件 在学习完Linux权限后&#xff0c;我们清楚的知道&#xff1a;文…

【JVM】内存模型

文章目录 内存模型的基本概念案例 程序计数器栈Java虚拟机栈局部变量表栈帧中局部变量表的实际状态栈帧中存放的数据有哪些 操作数栈帧数据 本地方法栈 堆堆空间是如何进行管理的? 方法区静态变量存储 直接内存直接内存的作用 内存模型的基本概念 在前面的学习中,我们知道了字…

论文笔记:Pre-training to Match for Unified Low-shot Relation Extraction

论文来源&#xff1a;ACL 2022 论文地址&#xff1a;https://aclanthology.org/2022.acl-long.397.pdf 论文代码&#xff1a;https://github.com/fc-liu/MCMN &#xff08;笔记不易&#xff0c;请勿恶意转载抄袭&#xff01;&#xff01;&#xff01;&#xff09; 目录 A…

从头预训练一只迷你 LLaMA 3_llama3 预训练预处理

我将向你展示如何使用 LLama 3.1&#xff08;一个本地运行的模型&#xff09;来执行GraphRAG操作&#xff0c;总共就50号代码。。。 首先&#xff0c;什么是GraphRAG&#xff1f;GraphRAG是一种通过考虑实体和文档之间的关系来执行检索增强生成的方式&#xff0c;关键概念是节…