设计模式:工厂方法模式

工厂模式属于创建型模式,也被称为多态工厂模式,它在创建对象时提供了一种封装机制,将实际创建对象的代码与使用代码分离,有子类决定要实例化的产品是哪一个,把产品的实例化推迟到子类。

使用场景

  • 重复代码 : 创建对象 需要使用 大量重复的代码 ;
  • 不关心创建过程 : 客户端 不依赖 产品类 , 不关心 实例 如何被创建 , 实现等细节 ;
  • 创建对象 : 一个类 通过其 子类 来 指定 创建哪个对象 ;

 工厂方法模式的角色

  • 抽象产品(Product)是定义产品的接口,是工厂方法模式创建对象的父类,也就是产品对象的公共父类。
  • 产品类(ConcreteProduct)是实现了抽象产品所声明的接口,工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。
  • 抽象工厂(Factory)是工厂方法模式的核心,所有创建对象的工厂类都必须继承该接口。
  • 具体工厂(ConcreteFactory)是抽象工厂的子类,实现了抽象工厂中定义的函数,工厂方法模式所创建的每一个对象都是某个具体产品类的实例。

结构图 

优缺点

优点

  • 不关心创建细节 : 用户 只需要 关心 所需产品 对应的工厂 , 无需关心创建细节 ;
  • 符合开闭原则 : 加入 新产品 , 符合开闭原则 , 提高可扩展性 ;

缺点

  • 增加复杂性:类的个数容易过多,增加系统复杂度;在添加新产品时,除了编写 新的产品类之外 ,还要 编写该产品类对应的工厂类。
  • 增加难度:增加了系统抽象性和理解难度。工厂方法本身利用了抽象,该模式中会 引入抽象层 ,如果要动态创建产品类,还要 引入反射技术。

应用实例 

创建一个 Shape 接口和实现 Shape 接口的实体类。下一步是定义工厂类 ShapeFactory

FactoryPatternDemo 类使用 ShapeFactory 来获取 Shape 对象。它将向 ShapeFactory 传递信息(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。

抽象产品

public interface Shape {
   void draw();
}

 实现接口的产品类

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



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



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

抽象工厂

public interface Factory {
    
   public Shape getShape(String shapeType);
}

具体工厂

public class ShapeFactory implements Factory {
    
   //使用 getShape 方法获取形状类型的对象
   @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;
   }
}

使用该工厂,通过传递类型信息来获取实体类的对象

public class FactoryPatternDemo {
 
   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();
 
      //获取 Circle 的对象,并调用它的 draw 方法
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //调用 Circle 的 draw 方法
      shape1.draw();
 
      //获取 Rectangle 的对象,并调用它的 draw 方法
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //调用 Rectangle 的 draw 方法
      shape2.draw();
 
      //获取 Square 的对象,并调用它的 draw 方法
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //调用 Square 的 draw 方法
      shape3.draw();
   }
}

运行结果

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.

 

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

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

相关文章

一文读懂mysql的锁

提起mysql的锁,你是否会似懂非懂,最常听人提起的就是乐观锁,悲观锁、排他锁、共享锁 悲观锁是用 select c form T for update然后等待提交实现的,但是你知道吗,其实排他锁和悲观锁其实是一回事!&#xff0…

redis-4 搭建redis集群

1.为什么需要redis集群? Redis 集群提供了高可用性、横向扩展和数据分片等功能,使得 Redis 能够应对大规模的数据存储和高并发访问的需求。以下是一些需要使用 Redis 集群的常见情况: 高可用性:通过在多个节点之间进行数据复制和…

假期刷题打卡--Day17

1、MT1163孪生质数 在质数中,若两个质数之差为2,我们称之为孪生质数,例如(3、5)(5、7),输入2个正整数,判断他是不是孪生质数,输出YES或者NO。 格式 输入格式: 输入整…

求职就业,你需要了解人才测评的应用流程

很多求职者心中都有一个困惑,不知道该人才测评的流程是如何进行,只知道完成基本的测试,完全不明白测试过程如何进行。但实际上,这个过程十分简单,并不像传说中那样神秘,很多人都能够弄懂过程的原理。一旦熟…

一文搞懂如何开通miniQMT(全网最清晰版本)

前言 本篇文章,目的是说清楚如何开通miniQMT,给出最清晰的开通路径。关于miniQMT是什么,可以参考我之前的文章《什么是miniQMT?》 1、开通券商版QMT 首先,迅投的QMT软件,与大部分券商都存在深度合作。也就是说&…

hadoop面试题

0. 思维导图 1. HDFS 1. HDFS的架构♥♥ HDFS主要包括三个部分,namenode,datanode以及secondary namenode。这里主要讲一下他们的作用:namenode主要负责存储数据的元数据信息,不存储实际的数据块,而datanode就是存储实际的数据块…

【.NET Core】深入理解C#中的特殊字符

【.NET Core】深入理解C#中的特殊字符 文章目录 【.NET Core】深入理解C#中的特殊字符一、概述二、$-- 字符串内插2.1 内插字符串的结构2.2 内插原始字符串字面量2.3 特殊字符2.4 内插字符串编译 三、-- 逐字字符串标识符四、“”“--原始字符串文本 一、概述 特殊字符是预定义…

【计算机网络】中小型校园网构建与配置

拓扑图配置文件传送门 Packet Tracer-中小型校园网配置布局文件文件 相关文章 【计算机网络】IP协议及动态路由算法 【计算机网络】Socket通信编程与传输协议分析 【计算机网络】网络应用通信基本原理 原理 1. Network 广域网,WAN Wide Area Network&#xff…

微信小程序-支付功能-整合springboot功能

微信小程序-支付功能 首先我这里得声明,微信支付比较繁琐,所以我写的都很仔细,所以如果你没有耐心的化,应该是看不下去的,我力求,以后我们用到微信支付代码的时候,我看到这个文章就能很好的搭起来,而不是直接抄别人的代码,我觉得学的还是一个思想,和框架,了解它整体的流程,以后…

网页转文件下载工具

为了更快捷copy博客 做了个 网页转文件下载工具 1.0.1 更新如下: javaphpjava提供页面转换文件的微服务APIphp调用接口,输出文件下载支持网页转md 1.0.2 更新如下: 样式表切换,白天or黑夜,cookie七天保质期 未…

网络原理,网络通信以及网络协议

​​​​💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录专栏:网络原理,网络通信以及网络协议 🎉欢迎大家点赞👍评论📝收藏⭐文章 文章目录 网络原理概念网络通信局域网LAN广域网WAN 网络通信IP地址端口号…

【GitHub项目推荐--GPT开源项目】【转载】

Auto-GPT Auto-GPT 是一个实验性的开源项目,基于 GPT-4。你给出 Auto-GPT 一个的任务,它不会立即输出答案,而会先自己通过多轮对话来琢磨、验证、决策,从而自己找出一条达成目标的路,整个过程完全不需要人类插手&…

LeetCode:376.摆动序列

个人主页:仍有未知等待探索-CSDN博客 专题分栏:算法_仍有未知等待探索的博客-CSDN博客 题目链接:376. 摆动序列 - 力扣(LeetCode) 一、题目 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称…

【CANoe使用大全】——离线回放数据

🙋‍♂️【CANoe使用大全】系列💁‍♂️点击跳转 文章目录 1.概述2.Offline3.综述 1.概述 本章主要介绍数据的离线回放操作 2.Offline 导入需要加载的文件 导入完成效果: 点击开关便可进行数据回放 3.综述 Offline回放主要配合Trace和…

夏目友人帐 第五季 2016.10.04

夏目友人帐 第五季 2016.10.04 第1话:一如既往的样子 / 変わらぬ姿第2话:恶作剧之雨 / 悪戯な雨第3话:除妖人寄来的信 / 祓い屋からの手纸第4话:连锁的背后 / 连锁の阴第5话:不可结缘 / 结んではいけない第6话&#xf…

java eazyexcel 实现excel的动态多级联动下拉列表(2)使用MATCH+OFFSET函数

原理 同样是将数据源放到一个新建的隐藏的sheet中,第一行是第一个列表的数据,第二行是每一个有下级菜单的菜单,他下面的行就是他下级菜单的每一值使用MATCH函数从第二行找到上级菜单对应的列根据OFFSET函数从2中获取的列,取得下级…

python基础3

7.5 range range 可以生成数字供 for 循环遍历 , 它可以传递三个参数,分别表示 起始、结束和步长。 8. 数据类型高级 8.1 字符串高级 字符串的常见操作包括: 获取长度 :len len 函数可以获取字符串的长度。 查找内容 :find 查找指定内容在字符…

大创项目推荐 题目: 基于深度学习的疲劳驾驶检测 深度学习

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 🔥 优…

【智能家居】6、语音控制及网络控制代码实现

一、语音控制 1、指令结构体编写 这个结构体定义了一个命令输入的模型。在这个模型中,包含以下几个部分: cmdName:一个长度为128的字符串,用于存储命令名称。dvicesName:一个长度为128的字符串,用于存储设备名称。cmd:一个长度为32的字符串,用于存储具体的命令。Init:…

数据结构-线性表

文章目录 数据结构—线性表1.线性表的定义和基本操作线性表的定义线性表的特点线性表的基本操作 2.线性表的顺序存储和链式存储表示顺序存储链式存储单链表循环链表双向链表 数据结构—线性表 1.线性表的定义和基本操作 线性表的定义 定义:线性表是具有相同数据类…