设计模式-抽象工厂模式

抽象工厂模式

    • 1、抽象工厂模式简介
    • 2、具体实现

1、抽象工厂模式简介

  抽象工厂模式(Abstract Factory Pattern)在工厂模式尚添加了一个创建不同工厂的抽象接口(抽象类或接口实现),该接口可叫做超级工厂。在使用过程中,我们首先通过抽象接口创建不同的工厂对象,然后根据不同的工厂对象创建不同的对象。

  我们可以将工厂模式理解为针对一个产品维度进行分类,比如上述工厂模式下的苹果手机和华为手机;而抽象工厂模式针对的是多个产品维度的分类,比如苹果公司既制造苹果手机又制造苹果笔记本电脑,同样,华为公司既制造华为手机也制造华为笔记本电脑。

  在同一个厂商有多个维度的产品时,如果使用工厂模式,则势必会存在多个独立的工厂,这样的话,设计和物理世界是不对应的,正确的做法是通过抽象工厂模式来实现。我们可以将抽象工厂类比成厂商(苹果、华为),将通过抽象工厂创建出来的工厂类比成不同产品的生产线(手机生产线、笔记本电脑生产线),在需要生产产品时根据抽象工厂生产。

  工厂模式定义了工厂方法来实现不同厂商手机的制造。可是问题来了,我们知道苹果公司和华为公司不仅制造手机,还制造电脑。如果使用工厂模式,就需要实现两个工厂类,并且这两个工厂类没有多大关系,这样的设计显然不够优雅,那么如何实现呢?使用抽象工厂就能很好地解决上述问题。我们定义一个抽象工厂,在抽象工厂中定义好要生产的产品(手机或者电脑),然后在抽象工厂的实现类中根据不同类型的产品和产品规格生产不同的产品返回给用户。
在这里插入图片描述

2、具体实现

  第1类产品的手机接口及其实现类的定义如下:

public interface Phone {
    String call();
}
public class PhoneApple implements Phone {
    @Override
    public String call() {
        return "call somebody by apple phone";
    }
}
public class PhoneHuaWei implements Phone {
    @Override
    public String call() {
        return "call somebody by huawei phone";
    }
}

  以上代码定义了Phone的接口及其实现类PhoneApplePhoneHuaWei。在该接口中定义了一个打电话的方法call(),实现类根据其品牌打印相关信息。

  第1类产品的手机工厂类的定义如下:

public class PhoneFactory extends AbstractFactory{
    @Override
    public Phone createPhone(String brand) {
        if("HuaWei".equals(brand)){
            return new PhoneHuaWei();
        }else if("Apple".equals(brand)){
            return new PhoneApple();
        }else{
            return null;
        }
    }

    @Override
    public Computer createComputer(String brand) {
        return null;
    }
}

  以上代码定义了PhoneFactory的手机工厂类,该类继承了AbstractFactory并实现了方法createPhone(),createPhone()根据不同的此参数实例化不同品牌的手机类并返回。在createPhone()的参数为“HuaWei”时,工厂类为我们实例化一个PhoneHuaWei类的实例并返回;在createPhone()的参数为"Apple"时,工厂类为我们实例化一个PhoneApple类的实例并返回,这样便满足了工厂根据不同参数生产不同产品的需求。

  第2类产品的电脑接口及实现类的定义如下:

public interface Computer {
    String internet();
}
public class ComputerApple implements Computer {
    @Override
    public String internet() {
        return "surf the internet by apple computer";
    }
}
public class ComputerHuaWei implements Computer {
    @Override
    public String internet() {
        return "surf the internet by huawei computer";
    }
}

  以上代码定义了Computer的电脑接口及其实现类ComputerAppleComputerHuaWei。在该接口中定义了一个上网的方法internet(),实现类根据其品牌打印相关信息。

  第2类产品的电脑工厂类定义如下:

public class ComputerFactory extends AbstractFactory {
    @Override
    public Phone createPhone(String brand) {
        return null;
    }

    @Override
    public Computer createComputer(String brand) {
        if("HuaWei".equals(brand)){
            return new ComputerHuaWei();
        }else if("Apple".equals(brand)){
            return new ComputerApple();
        }else{
            return null;
        }
    }
}

  以上代码定义了ComputerFactory的手机工厂类,该类继承了AbstractFactory并实现了方法createComputer(),createComputer()根据不同的此参数实例化不同品牌的电脑类并返回。在createComputer()的参数为“HuaWei”时,工厂类为我们实例化一个ComputerHuaWei类的实例并返回;在createComputer()的参数为"Apple"时,工厂类为我们实例化一个ComputerApple类的实例并返回,这样便满足了工厂根据不同参数生产不同产品的需求。

  抽象工厂的定义如下:

public abstract class AbstractFactory {
    public abstract Phone createPhone(String brand);
    public abstract Computer createComputer(String brand);
}

  以上代码定义了抽象类AbstractFactory,这个类是抽象工厂的核心类,它定义了两个方法createPhone()createComputer(),用户在需要手机时调用其createPhone()构造一个手机(华为或者苹果品牌)即可,用户在需要电脑时调用其createComputer()构造一个电脑(华为或者苹果品牌)即可。

  使用抽象工厂:

//使用抽象工厂
public static void main(String[] args) {
    PhoneFactory phoneFactory = new PhoneFactory();
    Phone huaWei = phoneFactory.createPhone("HuaWei");
    Phone apple = phoneFactory.createPhone("Apple");
    System.out.println(huaWei.call());
    System.out.println(apple.call());

    ComputerFactory computerFactory = new ComputerFactory();
    Computer computerHuaWei = computerFactory.createComputer("HuaWei");
    Computer computerApple = computerFactory.createComputer("Apple");
    System.out.println(computerHuaWei.internet());
    System.out.println(computerApple.internet());
}

  以上代码使用了我们定义好的抽象工厂,在需要生产商品时,首先需要定义一个抽象的工厂类AbstractFactory,然后使用抽象的工厂类生产不同的工厂类,最终根据不同的工厂生产不同的产品。运行结果如下:

image-20230612000119182

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

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

相关文章

【HTML界面设计(二)】说说模块、登录界面

记录很早之前写的前端界面(具体时间有点久远) 一、说说模板 采用 适配器(Adapter)原理 来设计这款说说模板,首先看一下完整效果 这是demo样图,需要通过业务需求进行修改的部分 这一部分,就是dem…

Redis系列--布隆过滤器(Bloom Filter)

一、前言 在实际开发中,会遇到很多要判断一个元素是否在某个集合中的业务场景,类似于垃圾邮件的识别,恶意ip地址的访问,缓存穿透等情况。类似于缓存穿透这种情况,有许多的解决方法,如:redis存储…

宏景eHR SQL注入漏洞复现(CNVD-2023-08743)

0x01 产品简介 宏景eHR人力资源管理软件是一款人力资源管理与数字化应用相融合,满足动态化、协同化、流程化、战略化需求的软件。 0x02 漏洞概述 宏景eHR 存在SQL注入漏洞,未经过身份认证的远程攻击者可利用此漏洞执行任意SQL指令,从而窃取数…

如何在大规模服务中迁移缓存

当您启动初始服务时,通常会过度设计以考虑大量流量。但是,当您的服务达到爆炸式增长阶段,或者如果您的服务请求和处理大量流量时,您将需要重新考虑您的架构以适应它。糟糕的系统设计导致难以扩展或无法满足处理大量流量的需求&…

docker基础

文章目录 通过Vagrant安装虚拟机修改虚拟机网络配置 docker CE安装(在linux上)docker desktop安装(在MacOS上)Docker架构关于-阿里云镜像加速服务配置centos卸载docker 官网: http://www.docker.com 仓库: https://hub.docker.com Docker安装在虚拟机上,可以通过V…

Go语言的TCP和HTTP网络服务基础

目录 【TCP Socket 编程模型】 Socket读操作 【HTTP网络服务】 HTTP客户端 HTTP服务端 TCP/IP 网络模型实现了两种传输层协议:TCP 和 UDP,其中TCP 是面向连接的流协议,为通信的两端提供稳定可靠的数据传输服务;UDP 提供了一种…

[MySQL]不就是SQL语句

前言 本期主要的学习目标是SQl语句中的DDL和DML实现对数据库的操作和增删改功能,学习完本章节之后需要对SQL语句手到擒来。 1.SQL语句基本介绍 SQL(Structured Query Language)是一种用于管理关系型数据库的编程语言。它允许用户在数据库中存…

双因素身份验证在远程访问中的重要性

在快速发展的数字环境中,远程访问计算机和其他设备已成为企业运营的必要条件。无论是在家庭办公室运营的小型初创公司,还是团队分散在全球各地的跨国公司,远程访问解决方案都能保证工作效率和连接性,能够跨越距离和时间的阻碍。 …

7Z045 引脚功能详解

本文针对7Z045芯片,详细讲解硬件设计需要注意的技术点,可以作为设计和检查时候的参考文件。问了方便实用,按照Bank顺序排列,包含配置Bank、HR Bank、HP Bank、GTX Bank、供电引脚等。 参考文档包括: ds191-XC7Z030-X…

怎么计算 flex-shrink 的缩放尺寸

计算公式: 子元素的宽度 - (子元素的宽度的总和 - 父盒子的宽度) * (某个元素的flex-shrink / flex-shrink总和) 面试问题是这样的下面 left 和 right 的宽度分别是多少 * {padding: 0;margin: 0;}.container {width: 500px;height: 300px;display: flex;}.left {width: 500px…

红日靶场(一)外网到内网速通

红日靶场(一) 下载地址:http://vulnstack.qiyuanxuetang.net/vuln/detail/2/ win7:双网卡机器 win2003:域内机器 win2008域控 web阶段 访问目标机器 先进行一波信息收集,扫一下端口和目录 扫到phpmyadmin,还有一堆…

【资料分享】Xilinx Zynq-7010/7020工业核心板规格书(双核ARM Cortex-A9 + FPGA,主频766MHz)

1 核心板简介 创龙科技SOM-TLZ7x是一款基于Xilinx Zynq-7000系列XC7Z010/XC7Z020高性能低功耗处理器设计的异构多核SoC工业核心板,处理器集成PS端双核ARM Cortex-A9 PL端Artix-7架构28nm可编程逻辑资源,通过工业级B2B连接器引出千兆网口、USB、CAN、UA…

Triton教程 --- 动态批处理

Triton教程 — 动态批处理 Triton系列教程: 快速开始利用Triton部署你自己的模型Triton架构模型仓库存储代理模型设置优化动态批处理 Triton 提供了动态批处理功能,将多个请求组合在一起执行同一模型以提供更大的吞吐量。 默认情况下,只有当每个输入在…

【开源与项目实战:开源实战】81 | 开源实战三(上):借Google Guava学习发现和开发通用功能模块

上几节课,我们拿 Unix 这个超级大型开源软件的开发作为引子,从代码设计编写和研发管理两个角度,讲了如何应对大型复杂项目的开发。接下来,我们再讲一下 Google 开源的 Java 开发库 Google Guava。 Google Guava 是一个非常成功、…

io.netty学习(十一)Reactor 模型

目录 前言 传统服务的设计模型 NIO 分发模型 Reactor 模型 1、Reactor 处理请求的流程 2、Reactor 三种角色 单Reactor 单线程模型 1、消息处理流程 2、缺点 单Reactor 多线程模型 1、消息处理流程 2、缺点 主从Reactor 多线程模型 主从Reactor 多线程模型示例 1…

CTF-Show密码学:ZIP文件密码破解【暴力破解】

萌新 隐写23 题目内容: 文件的主人喜欢用生日做密码,而且还是个90后。 一、已知条件 在这个题目中,我们有以下已知条件: 文件的主人喜欢用生日做密码 - 这个条件告诉我们,密码可能是一个八位的纯数字密码&#xff0c…

云原生之深入解析如何正确计算Kubernetes容器CPU使用率

一、简介说明 使用 Prometheus 配置 kubernetes 环境中 Container 的 CPU 使用率时,会经常遇到 CPU 使用超出 100%,现在来分析一下: container_spec_cpu_period:当对容器进行 CPU 限制时,CFS 调度的时间窗口&#xff…

[架构之路-214]- UML-类图图解、详解、结构化、本质化讲解

目录 一、什么是类 1.1 概述 1.2 UML中类的表示 1.3 接口 1.4 抽象类 1.5 模板类 二、什么类图 2.1 概述 2.2 类关系 三、UML类图 3.1 结构关系 3.1.1 完全一体:继承关系 (类与类耦合度最高,类与类之间最强的关系) …

计算机基础知识

参考链接:https://blog.csdn.net/ChineseSoftware/article/details/123176978 https://www.cnblogs.com/8023-CHD/p/11067141.html https://blog.csdn.net/qq_42033567/article/details/108088514 http与https的区别 HTTP 的URL以http:// 开头,而HTTPS…

【Matlab】语音信号分析与处理实验报告

一、目的 使用Matlab分析与设计实验,理解与掌握以下知识点: 1、信号的采样、频谱混叠 2、信号的频谱分析 3、信号的幅度调制与解调方法 4、理想滤波器的时域和频域特性 5、数字滤波器的设计与实现 二、内容 1、录制一段个人的语音信号 2、采用合适的频…
最新文章