【设计模式】抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。

介绍

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

主要解决:主要解决接口选择的问题。

何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。

如何解决:在一个产品族里面,定义多个产品。

关键代码:在一个工厂里聚合多个同类产品。

应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。

注意事项:产品族难扩展,产品等级易扩展。

抽象工厂模式包含以下几个核心角色:

  • 抽象工厂(Abstract Factory):声明了一组用于创建产品对象的方法,每个方法对应一种产品类型。抽象工厂可以是接口或抽象类。
  • 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品对象的实例。
  • 抽象产品(Abstract Product):定义了一组产品对象的共同接口或抽象类,描述了产品对象的公共方法。
  • 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。

抽象工厂模式通常涉及一族相关的产品,每个具体工厂类负责创建该族中的具体产品。客户端通过使用抽象工厂接口来创建产品对象,而不需要直接使用具体产品的实现类。

实现

我们将创建 Shape 和 Color 接口和实现这些接口的实体类。下一步是创建抽象工厂类 AbstractFactory。接着定义工厂类 ShapeFactory 和 ColorFactory,这两个工厂类都是扩展了 AbstractFactory。然后创建一个工厂创造器/生成器类 FactoryProducer

AbstractFactoryPatternDemo 类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递形状信息 ShapeCIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递颜色信息 ColorRED / GREEN / BLUE),以便获取它所需对象的类型。

抽象工厂模式的 UML 图

步骤 1

为形状创建一个接口。

Shape.java

public interface Shape {
   void draw();
}

步骤 2

创建实现接口的实体类。

Rectangle.java

Rectangle.java

public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

Square.java

public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

Circle.java

public interface Color {
   void fill();
}

步骤 3

为颜色创建一个接口。

Color.java

public interface Color {
   void fill();
}

步骤4

创建实现接口的实体类。

Red.java

public class Red implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Red::fill() method.");
   }
}

Green.java

public class Green implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Green::fill() method.");
   }
}

Blue.java

public class Blue implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Blue::fill() method.");
   }
}

步骤 5

为 Color 和 Shape 对象创建抽象类来获取工厂。

AbstractFactory.java

public abstract class AbstractFactory {
   public abstract Color getColor(String color);
   public abstract Shape getShape(String shape);
}

步骤 6

创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象。

ShapeFactory.java

public class ShapeFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      return null;
   }
}

ColorFactory.java

public class ColorFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      if(color == null){
         return null;
      }        
      if(color.equalsIgnoreCase("RED")){
         return new Red();
      } else if(color.equalsIgnoreCase("GREEN")){
         return new Green();
      } else if(color.equalsIgnoreCase("BLUE")){
         return new Blue();
      }
      return null;
   }
}

步骤 7

创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂。

FactoryProducer.java

public class FactoryProducer {
   public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("SHAPE")){
         return new ShapeFactory();
      } else if(choice.equalsIgnoreCase("COLOR")){
         return new ColorFactory();
      }
      return null;
   }
}

步骤 8

使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象。

AbstractFactoryPatternDemo.java

public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
 
      //获取形状工厂
      AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
 
      //获取形状为 Circle 的对象
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //调用 Circle 的 draw 方法
      shape1.draw();
 
      //获取形状为 Rectangle 的对象
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //调用 Rectangle 的 draw 方法
      shape2.draw();
      
      //获取形状为 Square 的对象
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //调用 Square 的 draw 方法
      shape3.draw();
 
      //获取颜色工厂
      AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
 
      //获取颜色为 Red 的对象
      Color color1 = colorFactory.getColor("RED");
 
      //调用 Red 的 fill 方法
      color1.fill();
 
      //获取颜色为 Green 的对象
      Color color2 = colorFactory.getColor("GREEN");
 
      //调用 Green 的 fill 方法
      color2.fill();
 
      //获取颜色为 Blue 的对象
      Color color3 = colorFactory.getColor("BLUE");
 
      //调用 Blue 的 fill 方法
      color3.fill();
   }
}

步骤 9

执行程序,输出结果:

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.

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

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

相关文章

Jenkins改造—nginx配置鉴权

先kill掉8082的端口进程 netstat -natp | grep 8082 kill 10256 1、下载nginx nginx安装 EPEL 仓库中有 Nginx 的安装包。如果你还没有安装过 EPEL,可以通过运行下面的命令来完成安装 sudo yum install epel-release 输入以下命令来安装 Nginx sudo yum inst…

神经网络基础-神经网络补充概念-14-逻辑回归中损失函数的解释

概念 逻辑回归损失函数是用来衡量逻辑回归模型预测与实际观测之间差异的函数。它的目标是找到一组模型参数,使得预测结果尽可能接近实际观测。 理解 在逻辑回归中,常用的损失函数是对数似然损失(Log-Likelihood Loss)&#xff…

1.物联网LWIP网络,TCP/IP协议簇

一。TCP/IP协议簇 1.应用层:FTP,HTTP,Telent,DNS,RIP 2.传输层:TCP,UDP 3.网络层:IPV4,IPV6,OSPF,EIGRP 4.数据链路层:Ethernet&#…

Syncfusion Essential Studio JavaScrip Crack

Syncfusion Essential Studio JavaScrip Crack 数据透视表 添加了在将数据透视表导出到PDF文档时自定义列宽的支持。 签名 添加了对在特定位置绘制文本的支持。 Syncfusion Essential Studio for JavaScript在一个包中包含80多个高性能、轻量级、模块化和响应式UI组件。包括Jav…

dockerfile的概念

目录 一、Dockerfile 概念 1.1 docker镜像的分层 二、Docker镜像的创建 2.1 基于已有的镜像创建 2.2 基于本地模板创建 2.3 基于dockerfile创建 2.3.1 dockerfile 结构(四部分) 三、Dockerfile操作指令 3.1 ENTRYPOINT指令 3.2 CMD 与entrypoint 3.3 小结 四、ADD和…

【JAVA】我们该如何规避代码中可能出现的错误?(一)

个人主页:【😊个人主页】 系列专栏:【❤️初识JAVA】 文章目录 前言三种类型的异常异常处理JAVA内置异常类Exception 类的层次 前言 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的&…

什么是CSS Grid布局?什么是Flexbox布局?它们两者有什么不同?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS Grid布局⭐ Flexbox布局⭐ 不同之处⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web…

Python“牵手”lazada商品评论数据采集方法,lazadaAPI申请指南

lazada平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范,lazadaAPI接口是指通过编程的方式,让开发者能够通过HTTP协议直接访问lazada平台的数据,包括商品信息、店铺信息、物流信息等,从而实现la…

【第八讲---视觉里程计2】

在图像中提取特征点并计算特征描述,非常耗时 通过计算描述子距离在不同图像中寻找特征匹配,也非常耗时 利用通过匹配点信息计算相机位姿,没什么问题 我们可以采用以下方法进行改进: 光流:通过其他方式寻找匹配点直接法…

Python Opencv实践 - 图像均值滤波

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) print(img.shape) pixel_count img.shape[0] * img.shape[1] print(pixel_count)#为图像添加椒盐噪声 #参考资料&#xf…

Android性能优化----执行时间优化

作者:lu人皆知 在APP做启动优化时,Application会做一些初始化的工作,但不要在Application中做耗时操作,然而有些初始化工作可能是很耗时的,那怎么办?初始化操作可以开启子线程来完成。 计算执行时间 常规…

学无止境·运维高阶⑤(LVS-DR 群集 配置Nginx负载均衡)

LVS-DR 群集 && 配置Nginx负载均衡 一、LVS-DR 群集1、相关配置环境2、在RS上配置并启动脚本2.1相关脚本2.2 启动脚本,另一台RS同样步骤 3、LVS-DR模式配置脚本4、测试 二、Nginx负载均衡1、安装Nginx并关闭相应设置2、向主机 node2,node3 写入内…

Spring Clould 消息队列 - RabbitMQ

视频地址:微服务(SpringCloudRabbitMQDockerRedis搜索分布式) 初识MQ-同步通讯的优缺点(P61,P62) 同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话&…

比ChatGPT更强的星火大模型V2版本发布!

初体验 测试PPT生成 结果: 达到了我的预期,只需要微调就可以直接交付,这点比ChatGPT要强很多. 测试文档问答 结果: 这点很新颖,现在类似这种文档问答的AI平台收费都贵的离谱,星火不但免费支持而且效果也…

TiDB v7.1.0 跨业务系统多租户解决方案

本文介绍了 TiDB 数据库的资源管控技术,并通过业务测试验证了效果。资源管控技术旨在解决多业务共用一个集群时的资源隔离和负载问题,通过资源组概念,可以限制不同业务的计算和 I/O 资源,实现资源隔离和优先级调度,提高…

优思学院|六西格玛黑带的9大任务和7大技能

六西格玛黑带是六西格玛管理中最为重要的一个角色,他们专职(也可以是兼职)从事六西格玛改进项目,是成功完成六西格玛项目的技术骨干成员,是六西格玛组织的核心力量。他们的努力程度决定着六西格玛管理的成败。 六西格玛…

新榜 | CityWalk本地生活商业价值洞察报告

如果说现在有人问,最新的网络热词是什么? “CityWalk”,这可能是大多数人的答案。 近段时间,“CityWalk”刷屏了各种社交媒体,给网友们带来了一场“城市漫步”之旅。 脱离群体狂欢,这个在社交媒体引发热议的词汇背后又…

HCIP VLAN实验

VLAN实验 拓扑图配置和分析分析配置LSW1LSW2R1 测试dhcp获取ipICMP测试 拓扑图 配置和分析 分析 从题目来看,因为 pc 1 3都是vlan2而且还是不同网段,pc 2 4 5 6在同一网段,所以可以将pc 1 2 5 4 6分在一个网段 pc4不通5 6 ,那就…

【sgDragSize】自定义拖拽修改DIV尺寸组件,适用于窗体大小调整

核心原理就是在四条边、四个顶点加上透明的div,给不同方向提供按下移动鼠标监听 ,对应计算宽度高度、坐标变化 特性: 支持设置拖拽的最小宽度、最小高度、最大宽度、最大高度可以双击某一条边,最大化对应方向的尺寸;再…

JVM——配置常用参数,GC调优策略

文章目录 JVM 配置常用参数Java内存区域常见配置参数概览堆参数回收器参数项目中常用配置常用组合 常用 GC 调优策略GC 调优原则GC 调优目的GC 调优策略 JVM 配置常用参数 Java内存区域常见配置参数概览堆参数;回收器参数;项目中常用配置;常…
最新文章