【设计模式-5】抽象工厂模式的代码实现及使用场景

 前面我们了解到工厂方法模式通过引入抽象工厂的概念,使得产品对象的创建可以依赖于具体工厂,但是这种设计模式最大的问题是会造成类的数量爆炸式增长。对于这个问题,抽象工厂模式通过引入两个新的概念:产品等级与产品簇,来解决工厂方法的工厂类过多的问题。

 在正式进入抽象工厂模式学习之前,我们先来了解一下这两个概念:

  • 产品等级(分类): 产品等级可以理解为一类相同的产品,可以理解为抽象产品下的子类实现。具体表现为,比如电视机是一类产品,可以有海尔电视机、小米电视机、TCL电视机等,这个电视系列就可以理解为一个产品等级。
  • 产品簇: 产品簇可以理解为一组不同等级产品的组合,但是这些产品都是一个工厂的产品。具体表现为,比如海尔工厂生产电视机、电冰箱、洗衣机等,这些海尔生产的电器产品组合在一起形成一个产品簇。
    在这里插入图片描述

1. 概述

抽象工厂模式:为创建一组对象提供了一种解决方案,与工厂方法模式相比,抽象工厂模式中的工厂角色不只创建一种产品,而是负责一个产品簇对象的生产。抽象工厂模式是一种创建型的设计模式。
 在抽象工厂模式中,包含4个角色:

  • 抽象工厂角色: 它声明了一组用于创建一个产品簇的方法,每个方法对应一种产品,它可以是接口或者抽象类。
  • 具体工厂角色: 它实现了在抽象工厂中声明的创建具体产品的方法,生成一组具体的产品,这些产品组成一个产品簇,每种产品都属于一个产品等级。
  • 抽象产品角色: 它是每种产品的抽象,可以是接口或者抽象类,声明产品的业务方法。
  • 具体产品角色: 它继承抽象产品,实现了抽象产品中声明的业务方法,多个具体产品可以组成一个产品簇。

2. 代码实现

 抽象工厂模式是一类比较复杂的对象创建型模式,复杂的地方在于产品簇和产品等级维度的划分,有时候业务界限比较模糊,这些都高度依赖于开发人员的业务素养和代码积累等。

 接下来我们就以刚才海尔、美的工厂生产冰箱和电视机的产品为例子,写一个demo:

  • 抽象的工厂接口
public interface AbstractFactory {
    // 创建电视的方法
    TelevisionProduct createTelevisionProduct();
    // 创建冰箱的方法
    RefrigeratorProduct createRefrigeratorProduct();
}
  • 具体的实现类
/**
 * 美的生产工厂
 */
class MideaFactory implements AbstractFactory {
    // 实现创建电视的方法
    @Override
    public TelevisionProduct createTelevisionProduct() {
        return new MideaTelevisionProduct();
    }
    // 创建冰箱的方法
    @Override
    public RefrigeratorProduct createRefrigeratorProduct() {
        return new MideaRefrigeratorProduct();
    }
}

/**
 * 海尔生产工厂
 */
class HairFactory implements AbstractFactory {
    // 实现创建电视的方法
    @Override
    public TelevisionProduct createTelevisionProduct() {
        return new HairTelevisionProduct();
    }
    // 创建冰箱的方法
    @Override
    public RefrigeratorProduct createRefrigeratorProduct() {
        return new HairRefrigeratorProduct();
    }
}
  • 抽象的产品角色
// 产品簇-冰箱产品
public interface RefrigeratorProduct {
    void displayColor();
}

// 产品簇-电视机产品
public interface TelevisionProduct {
    void displayShape();
}
  • 具体的产品角色
// 海尔冰箱
public class HairRefrigeratorProduct implements RefrigeratorProduct {
    @Override
    public void displayColor() {
        System.out.println("海尔冰箱");
    }
}
// 海尔电视机
public class HairTelevisionProduct implements TelevisionProduct{
    @Override
    public void displayShape() {
        System.out.println("海尔电视机");
    }
}
// 美的冰箱
public class MideaRefrigeratorProduct implements RefrigeratorProduct {
    @Override
    public void displayColor() {
        System.out.println("美的冰箱");
    }
}
// 美的电视机
public class MideaTelevisionProduct implements TelevisionProduct{
    @Override
    public void displayShape() {
        System.out.println("美的电视机");
    }
}
  • 客户端及运行结果
class Client {
   public static void main(String[] args) {
       // 美的工厂的产品簇
       AbstractFactory mideaFactory = new MideaFactory();
       RefrigeratorProduct mideaRefrigerator = mideaFactory.createRefrigeratorProduct();
       mideaRefrigerator.displayColor();
       TelevisionProduct mideaTelevision = mideaFactory.createTelevisionProduct();
       mideaTelevision.displayShape();

       System.out.println("========分割线========");
       // 海尔工厂的产品簇
       HairFactory hairFactory = new HairFactory();
       RefrigeratorProduct hairRefrigerator = hairFactory.createRefrigeratorProduct();
       hairRefrigerator.displayColor();
       TelevisionProduct hairTelevision = hairFactory.createTelevisionProduct();
       hairTelevision.displayShape();
   }
}
美的冰箱
美的电视机
========分割线========
海尔冰箱
海尔电视机

3. UML类图

 基于上面的这个抽象工厂的Demo,我们来画一下抽象工厂模式的UML类图。

在这里插入图片描述

4. 总结

 抽象工厂模式是工厂方法模式的进一步延伸,在一些框架和API的类库设计中都得到了广泛的使用。下面,我们来总结一下这种设计模式的优缺点

4.1 优点

  • 对象的创建和使用过程分离,用户无需关注对象的创建,只需要会使用工厂模式即可;
  • 抽象工厂模式使得同一个产品簇的对象可以同时被创建,可以使得用户能同时使用这一个产品簇的对象;
  • 产品簇维度的扩展很方便,直接增加实现即可,符合开闭原则。

4.2 缺点

 抽象工作的缺点也很明显,像扩展产品分类是比较麻烦的,涉及到多个接口和类的关联修改,违背了开闭原则。

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

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

相关文章

ant-design-vue 使用本地iconfont.js

createFromIconfontCN只能使用【在线资源】,但是在线资源存在不稳定的风险 有人提了issue,不过目前也没有解决,但是有人提出了一种新的的解决方案 参考链接: https://github.com/ant-design/ant-design/issues/16480 main.js im…

【UML建模】部署图(Deployment Diagram)

1.概述 部署图是一种结构图,用于描述软件系统在不同计算机硬件或设备上的部署和配置情况,以图形化的方式展示系统中组件、节点和连接之间的物理部署关系。 通过部署图,可以清晰地了解系统的物理结构和部署方式,包括系统组件和节…

prometheus grafana mysql监控配置使用

文章目录 前传bitnami/mysqld-exporter:0.15.1镜像出现了问题.my.cnf可以用这个"prom/mysqld-exporter:v0.15.0"镜像重要的事情mysql监控效果外传 前传 prometheus grafana的安装使用:https://nanxiang.blog.csdn.net/article/details/135384541 本文说…

软件测试|SQL AND和OR运算符解析

简介 在SQL(Structured Query Language)中,AND和OR是两个常用的逻辑运算符。它们用于组合条件来构建复杂的查询语句,帮助我们更精确地过滤和检索数据。本文将详细介绍SQL中的AND和OR运算符,包括其语法、用法以及使用时…

Matlab绘制动态心形线

1. 代码 for alpha0:0.1:30 x-1.8:0.001:1.8; y(x.^2).^(1/3)0.9*(3.3-x.^2).^(1/2).*sin(alpha*pi*x); plot(x,y,r-,LineWidth,1.2); set(gca,YGrid,on); axis([-3,3,-2,4]); text(-2,3.35,$f(x)x^{\frac{2}{3}}0.9(3.3-x^2)^{\frac{1}{2}}sin(\alpha\pi x)$,Interpreter,lat…

Python Gui图形化开发

PyQt5、Tkinter、Kivy等GUI工具,助你轻松构建Python应用。新手友好的PySimpleGUI,高交互性的PyForms,助你搭建理想用户界面。 学习编程,不仅要学习MySQL以及编程语言和并行架构之间的关系这类基础知识,还有一个重要的…

openGauss 5.0.0企业版一主一备安装部署

目录 一、环境准备 1. 华为云购买两台ECS 1.1查看openEuler版本,操作系统版本及CPU的制式是基础 1.2查看CPU模式 1.3操作系统环境准备 2. 集群配置XML文件准备: 2.1集群参数配置: 2.2主机参数配置: 2.3备机参数配置&…

静态网页设计——校园官网(HTML+CSS+JavaScript)

前言 声明:该文章只是做技术分享,若侵权请联系我删除。!! 使用技术:HTMLCSSJS 主要内容:对学校官网的结构进行模仿,对布局进行模仿。 主要内容 1、首页 首页以多个div对页面进行分割和布局…

Fiddler抓包工具之fiddler界面工具栏介绍

Fiddler界面工具栏介绍 (1)WinConfig:windows 使用了一种叫做“AppContainer”的隔离技术,使得一些流量无法正常捕获,在 fiddler中点击 WinConfig 按钮可以解除这个诅咒,这个与菜单栏 Tools→Win8 Loopback…

CSS 缩小旋转动画

<template><div class="container" @mouseenter="startAnimation" @mouseleave="stopAnimation"><!-- 旋方块 --><div class="box" :class="{ rotate-scale-down: isAnimating }"><!-- 元素内容…

bat批处理文件_输出内容到文本

文章目录 1、echo str > test.txt&#xff08;覆盖原有内容&#xff09;2、echo str >> test.txt&#xff08;不覆盖原有内容&#xff0c;追加&#xff09; 1、echo str > test.txt&#xff08;覆盖原有内容&#xff09; 2、echo str >> test.txt&#xff0…

JavaWeb基础(3)-会话技术(cookie和session),过滤器(Filter),监听器(Listener)

JavaWeb基础&#xff08;3&#xff09;-会话技术(cookie和session)&#xff0c;过滤器(Filter)&#xff0c;监听器(Listener) 文章目录 JavaWeb基础&#xff08;3&#xff09;-会话技术(cookie和session)&#xff0c;过滤器(Filter)&#xff0c;监听器(Listener)8 会话技术(Coo…

【28】Kotlin语法进阶——使用协程编写高效的并发程序

提示&#xff1a;此文章仅作为本人记录日常学习使用&#xff0c;若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、Kotlin中的协程1.1 协程的基本用法1.1.1协程与协程作用域1.1.2 使用launch函数创建子协程1.1.3 通过suspend关键声明挂起函数1.1.4 coroutineScope函数 1.2…

Spark调优解析-sparkshuffle和程序开发优化2(七)

1Shuffle调优 1.1调优概述 大多数Spark作业的性能主要就是消耗在了shuffle环节&#xff0c;因为该环节包含了大量的磁盘IO、序列化、网络数据传输等操作。因此&#xff0c;如果要让作业的性能更上一层楼&#xff0c;就有必要对shuffle过程进行调优。但是也必须提醒大家的是&a…

预判了预判,结局接受失败——2023年度总结

预判了预判&#xff0c;结局接受失败 引言一整年&#xff0c;你都在干什么活该解释我炒股前的上一份工作如何走上炒股之路计划的失败来得是那么干脆成功失败盈亏比失败预感与到来 失败的后果开始侵蚀得到失去 重新启程AI带来的改变当下的机会 新年Flag方向 总结 引言 时间过得…

【c++】入门3

引用 1.swap交换两个变量值的时候可以用引用 2.例题中通过前序遍历数组构建二叉树&#xff0c;可以用引用传别名. #include <stdio.h> #include <stdlib.h> typedef struct BinaryTreeNode {char data;struct BinaryTreeNode* left;struct BinaryTreeNode* right; …

gz-hamonic 安装提示缺少许多依赖无法安装

在软件更新源中增加gz-hamonic的软件源&#xff0c; 点击添加&#xff0c;在输入框中填入如下语句&#xff1a; deb http://packages.osrfoundation.org/ubuntu jammy main 如图所示&#xff1a; 然后执行 sudo apt -get install gz-hamonic即可安装。 如下图 在终端中输入…

FFmpeg调用MediaCodec解码

在前面的博文中我们介绍了关于使用NDK编译FFMpeg6.0的一些坑以及相关的解决方法。 详情请参考&#xff1a;NDK编译ffmpeg6.0与x264的坑 在写《NDK编译ffmpeg6.0与x264的坑》一文的时候就说过了&#xff0c;我们编译FFmpeg6.0的目的就是为了体验一下它NDK式的MediaCodec硬解码…

密码学:一文看懂初等数据加密一对称加密算法

文章目录 对称加密算法简述对称加密算法的由来对称加密算法的家谱数据加密标准-DES简述DES算法的消息传递模型DES算法的消息传递过程和Base64算法的消息传递模型的区别 算法的实现三重DES-DESede三重DES-DESede实现 高级数据加密标准一AES实现 国际数据加密标准-IDEA实现 基于口…

启发式算法解决TSP、0/1背包和电路板问题

1. Las Vegas 题目 设计一个 Las Vegas 随机算法&#xff0c;求解电路板布线问题。将该算法与分支限界算法结合&#xff0c;观察求解效率。 代码 python代码如下&#xff1a; # -*- coding: utf-8 -*- """ Date : 2024/1/4 Time : 16:21 Author : …