<设计模式> 工厂模式

工厂模式

  • 模式介绍:将对象的创建过程封装在工厂类中,客户端代码只需要关心从工厂获取对象的过程,而不需要了解对象的创建细节。这样做的好处包括提高了代码的灵活性和可扩展性,降低了对象之间的耦合度。
  • 主要解决接口选择的问题。当我们需要在不同条件下创建不同实例时。通过让子类实现工厂接口,返回一个抽象的产品。
  • 关键代码:对象的创建过程在子类中实现。

工厂模式的分类

工厂模式通常分为三种类型:简单工厂模式(静态工厂模式)、工厂方法模式和抽象工厂模式。

  1. 简单工厂模式(Simple Factory Pattern)
    1)定义:简单工厂模式又称静态工厂方法模式,它由一个工厂类根据传入的参数决定创建哪一种产品类的实例。
    2)优点:工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品。
    3)缺点:工厂类集中了所有产品的创建逻辑,一旦不能正常工作,整个系统都要受到影响;系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
  2. 工厂方法模式(Factory Method Pattern)
    1)定义:工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类中进行。
    2)优点:客户端不需要在代码中指定具体产品的类,只需要使用共同接口来操作实例;符合开闭原则,可以在不修改原有系统代码的情况下扩展新的产品类。
    3)缺点:每增加一个产品,就需要增加一个具体工厂类,增加了系统的复杂度。
  3. 抽象工厂模式(Abstract Factory Pattern)
    1)定义:抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
    2)优点:可以在类的内部对产品族进行约束,使得产品族内的产品可以替换;增加新的产品族很方便,只需增加一个新的工厂类,符合开闭原则。
    3)缺点:难以支持新种类的产品,因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品种类,则需要对接口进行扩展,这会影响到已有的系统结构。

应用场景

  • 数据库连接:为不同的数据库类型创建具体的工厂类,实现相应的数据库连接方法。
  • UI控件:为不同的UI控件类型创建具体的工厂类,实现相应的控件创建方法。
  • 文件处理:为不同的文件类型创建具体的工厂类,实现相应的文件处理方法。
  • 日志记录:为不同的日志类型创建具体的工厂类,实现相应的日志记录方法。
  • 网络通信:为不同的网络协议类型创建具体的工厂类,实现相应的网络通信方法。
  • 消息队列:为不同的消息队列类型创建具体的工厂类,实现相应的消息队列处理方法。
  • 数据结构:为不同的数据结构类型创建具体的工厂类,实现相应的数据结构操作方法。
  • 加密解密:为不同的加密解密算法类型创建具体的工厂类,实现相应的加密解密方法。
  • 消息推送:为不同的消息推送服务类型创建具体的工厂类,实现相应的推送方法。
  • 任务调度:为不同的任务调度服务类型创建具体的工厂类,实现相应的调度方法。

代码实现(AI Code)

一、简单工厂模式

/// <summary>
/// 日志记录器的接口
/// </summary>
public interface ILogger  
{  void Log(string message);  
}/// <summary>
/// ConsoleLogger实现日志记录器的接口
/// </summary>
public class ConsoleLogger : ILogger  
{  public void Log(string message)  {  Console.WriteLine($"ConsoleLogger: {message}");  }  
}  /// <summary>
/// FileLogger实现日志记录器的接口
/// </summary>
public class FileLogger : ILogger  
{  private string filePath;  public FileLogger(string filePath)  {  this.filePath = filePath;  }  public void Log(string message)  {  // 这里简单模拟写入文件  Console.WriteLine($"FileLogger ({filePath}): {message}");  // 实际使用中,你可能需要在这里写文件  }  
}/// <summary>
/// 日志记录器工厂
/// </summary>
public class LoggerFactory  
{  public static ILogger CreateLogger(string type)  {  switch (type)  {  case "console":  return new ConsoleLogger();  case "file":  // 假设我们默认日志路径为"app.log"  return new FileLogger("app.log");  default:  throw new ArgumentException("Invalid logger type");  }  }  
}class Program  
{  static void Main(string[] args)  {  ILogger logger1 = LoggerFactory.CreateLogger("console");  logger1.Log("This is a console log.");  ILogger logger2 = LoggerFactory.CreateLogger("file");  logger2.Log("This is a file log.");  // 如果尝试创建一个不存在的日志类型,将抛出异常  // ILogger logger3 = LoggerFactory.CreateLogger("unknown");  // logger3.Log("This will not work.");  }  
}

二、工厂模式

// 日志记录器接口  
public interface ILogger  
{  void Log(string message);  
}  // 控制台日志记录器  
public class ConsoleLogger : ILogger  
{  public void Log(string message)  {  Console.WriteLine($"Console: {message}");  }  
}  // 文件日志记录器  
public class FileLogger : ILogger  
{  private readonly string filePath;  public FileLogger(string filePath)  {  this.filePath = filePath;  }  public void Log(string message)  {  // 假设只是打印到控制台,实际应写入文件  Console.WriteLine($"File ({filePath}): {message}");  }  
}  // 日志工厂基类  
public abstract class LoggerFactory  
{  // 工厂方法  public abstract ILogger CreateLogger();  
}  // 控制台日志工厂  
public class ConsoleLoggerFactory : LoggerFactory  
{  public override ILogger CreateLogger()  {  return new ConsoleLogger();  }  
}  // 文件日志工厂  
public class FileLoggerFactory : LoggerFactory  
{  private readonly string filePath;  public FileLoggerFactory(string filePath)  {  this.filePath = filePath;  }  public override ILogger CreateLogger()  {  return new FileLogger(filePath);  }  
}  // 使用示例  
class Program  
{  static void Main(string[] args)  {  LoggerFactory consoleFactory = new ConsoleLoggerFactory();  ILogger consoleLogger = consoleFactory.CreateLogger();  consoleLogger.Log("This is a console log.");  LoggerFactory fileFactory = new FileLoggerFactory("app.log");  ILogger fileLogger = fileFactory.CreateLogger();  fileLogger.Log("This is a file log.");  }  
}

三、抽象工厂模式

  1. 定义产品接口
/ 日志记录器接口  
public interface ILogger  
{  void Log(string message);  
}  // 日志级别管理器接口(这里不实现具体类,仅作为示例)  
public interface ILogLevelManager  
{  // 可能包含设置日志级别、获取当前日志级别等方法  
}
  1. 创建具体产品类
// 控制台日志记录器  
public class ConsoleLogger : ILogger  
{  public void Log(string message)  {  Console.WriteLine($"Console: {message}");  }  
}  // 文件日志记录器  
public class FileLogger : ILogger  
{  private readonly string filePath;  public FileLogger(string filePath)  {  this.filePath = filePath;  }  public void Log(string message)  {  // 假设只是打印到控制台,实际应写入文件  Console.WriteLine($"File ({filePath}): {message}");  }  
}
  1. 定义抽象工厂接口
// 抽象工厂接口  
public interface ILoggingFactory  
{  ILogger CreateLogger();  // 如果需要,可以添加ILogLevelManager CreateLogLevelManager();  
}
  1. 创建具体工厂类
// 控制台日志工厂  
public class ConsoleLoggingFactory : ILoggingFactory  
{  public ILogger CreateLogger()  {  return new ConsoleLogger();  }  // 如果需要日志级别管理器,则在这里实现  // public ILogLevelManager CreateLogLevelManager() { ... }  
}  // 文件日志工厂  
public class FileLoggingFactory : ILoggingFactory  
{  private readonly string filePath;  public FileLoggingFactory(string filePath)  {  this.filePath = filePath;  }  public ILogger CreateLogger()  {  return new FileLogger(filePath);  }  // 如果需要日志级别管理器,则在这里实现,并可能依赖filePath  // public ILogLevelManager CreateLogLevelManager() { ... }  
}
  1. 使用抽象工厂
class Program  
{  static void Main(string[] args)  {  ILoggingFactory consoleFactory = new ConsoleLoggingFactory();  ILogger consoleLogger = consoleFactory.CreateLogger();  consoleLogger.Log("This is a console log.");  ILoggingFactory fileFactory = new FileLoggingFactory("app.log");  ILogger fileLogger = fileFactory.CreateLogger();  fileLogger.Log("This is a file log.");  }  
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 性能优化(二):LeakCanary【用于分析代码是否存在内存泄漏】程序无响应

目录 1&#xff09;内存相关的五种常见问题 2&#xff09;内存溢出和内存泄漏 3&#xff09;LeakCanary是什么? 4&#xff09;LeakCanary如何使用&#xff0c;如何分析&#xff1f; 5&#xff09;LeakCanary监测的内容 提问&#xff1a;程序有时候很卡&#xff0c;经常会出现…

前端开发:Vue2.0桌面组件库-Element

引入Element的步骤&#xff1a; 1.在vscode终端中执行命令&#xff08;需要联网&#xff09; 下载成功 2.在main.js中导入element.ui组件库。 同上&#xff0c;自定义的组件需要先在根组件中引入。 3.访问官网&#xff0c;复制调整代码

变阻器的主要特性和参数有哪些?

变阻器的主要特性和参数有很多&#xff0c;下面将详细介绍几个重要的特性和参数&#xff1a; 1. 电阻范围&#xff1a;滑动变阻器的电阻范围是指其最大电阻值和最小电阻值之间的范围&#xff0c;这个范围通常由制造商指定&#xff0c;用户在选择变阻器时需要根据实际需求选择合…

基于 SSM 的汽车租赁系统

基于 SSM 的电器网上订购系统 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Spring、JSP、MyBatis 工具&#xff1a;MyEclipse/IDEA、Tomcat 引言 汽车租赁是在约定时间内&#xff0c;租赁经营人将租赁汽车&#xff08;包括载货汽车和载客汽车&#x…

【机器学习】机器学习的详细阐述

机器学习&#xff08;Machine Learning, ML&#xff09;是一种通过从数据中学习来自适应改进预测和决策的人工智能技术。以下是对机器学习的详细阐述&#xff1a; 一、机器学习的定义 机器学习主要研究计算机系统对于特定任务的性能&#xff0c;逐步进行改善的算法和统计模型…

AFSim 仿真系统--子系统几何考虑

子系统几何考虑 概述 由于WSF试图表示以多种方式运行的子系统&#xff08;传感器&#xff0c;武器或通信&#xff09;&#xff0c;因此它提供的定义属性的机制&#xff0c;如几何限制&#xff0c;可能相当令人生畏。本文档提供了关于这些机制如何运作以及如何定义行为类似于真实…

Axure RP:打造动态交互的大屏可视化设计利器

Axure大屏可视化是指使用Axure RP这款原型设计工具来创建具有视觉冲击力和数据展示功能的大屏幕界面。Axure以其强大的交互设计和丰富的组件库&#xff0c;成为了实现大屏可视化的重要工具之一。以下是对Axure大屏可视化的详细阐述&#xff1a; 一、Axure在大屏可视化中的优势 …

给视频配背景音乐

介绍 给一段视频&#xff0c;想配个背景音乐&#xff0c;常规办法就是打开抖音或者剪映&#xff0c;咔咔咔一顿操作&#xff0c;完事儿&#xff0c;简单方便。但是如果你作为一个开发者呢&#xff0c;你又不能直接调用抖音剪映的接口吧&#xff08;特别有钱定制除外&#xff0…

ctfshow web入门 中期测评 web503--web516(无web511--web514)

web503 看了之前的文件的发现都没办法利用了 这个页面的源码发现了 layui.use([layer, form], function(){var layer layui.layer,form layui.form;form.on(submit(admin_settings), function(data){$.ajax({url:api/admin_settings.php,dataType:"json",type:po…

新手必看:Elasticsearch 入门全指南

Elasticsearch 入门介绍 Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;广泛应用于处理大规模数据和实时搜索需求。它基于 Apache Lucene 构建&#xff0c;具备高可扩展性和分布式特性&#xff0c;能够快速、可靠地存储、搜索和分析大量数据。本文将介绍 Elasti…

STM32项目分享:智能台灯(机智云)系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; https://www.bilibili.com/video/BV1My411q7fE…

CheckBox实现原理分析

CheckBox 是 Android 中的一个常用控件&#xff0c;用于实现复选框的功能。它继承自 CompoundButton&#xff0c;后者又继承自 Button。CheckBox 可以用来表示一个布尔值的选择状态&#xff0c;通常用于收集用户的选择&#xff0c;例如在表单中选择多个选项。 接下来&#xff…

小白学大模型:LLaMA-Factory 介绍与使用

最近这一两周看到不少互联网公司都已经开始秋招提前批了。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友…

基于CentOS Stream 9平台安装MySQL Community Server 9.0.1 Innovation

1. 安装之前 1.1 查看系统版本 cat /etc/redhat-releaseCentOS Stream release 9 1.2 查看cpu架构 lscpu架构&#xff1a; x86_64 CPU 运行模式&#xff1a; 32-bit, 64-bit 2. 官网下载 https://dev.mysql.com/downloads/mysql/ 要多看看 官方9.0文档&#xff1a;https://d…

C语言——输入你的身高和体重,测试你的健康状况。

输入你的身高和体重&#xff0c;测试你的健康状况。 计算bmi的值&#xff0c; bmi &#xff08;体重/身高的平方) 如果bmi 小于18.5&#xff0c;则显示“偏瘦&#xff0c;注意加强营养” 如果bmi 在18.5和23.9之间&#xff0c;则显示“体重指数良好&#xff0c;注意保持” 如果…

NSL-KDD入侵检测系统的设计与实现系列预告

每日进阶-基于机器学习的入侵检测系统——打怪升级之道 在当今的数字时代&#xff0c;网络安全不仅是防御&#xff0c;更是主动出击。你是否想知道如何用机器学习技术设计一套入侵检测系统&#xff08;IDS&#xff09;&#xff0c;让黑客无所遁形&#xff1f;本系列文章将为您揭…

unity2D游戏开发12单例

单例 我们先了解一种被称为单例的软件设计模式。当应用程序需要在生命周期内创建特定类的单个实例时,可以使用单例。当一个类提供了游戏中其他几个类使用的功能时,单例会很有用,例如,在Game Manager 类中协调游戏逻辑,单例可以提供对该类及其功能的公共统一访问入口。单例…

入门 PyQt6 看过来(案例)14~ 分组

本文分享一个分组框功能&#xff0c;采用pyqt6里的QGroupBox​控件&#xff0c;效果如下&#xff1a;性别和专业分开为两个分组框内&#xff1a; ​ 1 功能实现思路 ui页面布局设计 性别和专业要设计成两个分组框&#xff1a; ​ 逻辑实现 引入信号和槽函数来实现点击单选…

搞懂数据结构与Java实现

文章链接&#xff1a;搞懂数据结构与Java实现 (qq.com) 代码链接&#xff1a; Java实现数组模拟循环队列代码 (qq.com) Java实现数组模拟栈代码 (qq.com) Java实现链表代码 (qq.com) Java实现哈希表代码 (qq.com) Java实现二叉树代码 (qq.com) Java实现图代码 (qq.com)