<设计模式> 工厂模式

ops/2024/9/23 22:33:36/

工厂模式

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

工厂模式的分类

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

  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.ppmy.cn/ops/87659.html

相关文章

【Linux网络编程】套接字Socket(UDP)

网络编程基础概念&#xff1a; ip地址和端口号 ip地址是网络协议地址&#xff08;4字节32位&#xff0c;形式&#xff1a;xxx.xxx.xxx.xxx xxx在范围[0, 255]内&#xff09;&#xff0c;是IP协议提供的一种统一的地址格式&#xff0c;每台主机的ip地址不同&#xff0c;一个…

Redux

Redux的使用 和Vuex作用相同&#xff0c;但比Vuex学习成本高不可变值&#xff0c;纯函数面试常考 基本概念 store stateactionreducer 单向数据流 dispatch(action)reducer > newStatesubscribe 触发通知 react-redux import React from react import { Provider } f…

科普文:万字梳理高性能 Kafka快的8个原因

概叙 科普文&#xff1a;万字详解Kafka基本原理和应用-CSDN博客 科普文&#xff1a;万字梳理31个Kafka问题-CSDN博客 我们都知道 Kafka 是基于磁盘进行存储的&#xff0c;但 Kafka 官方又称其具有高性能、高吞吐、低延时的特点&#xff0c;其吞吐量动辄几十上百万。 在座的…

JavaScript之深入对象,详细讲讲构造函数与常见内置构造函数

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;我是前端菜鸟的自我修养&#xff01;今天给大家详细讲讲构造函数与常见内置构造函数&#xff0c;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;原创不易&#xff0c;如果能帮助到带大家&#xff0c;欢迎…

HTML入门(详细)

目录 前言 HTML是什么 HTML结构 认识HTML标签 HTML文件的基本结构 标签的层次结构 父子关系 兄弟关系 快速生成代码框架 HTML常见标签 注释标签 标题标签 h1-h6 段落标签 换行标签 格式化标签 图片标签 img 超链接标签 a 外部链接 内部链接 空链接 下载…

【C语言初阶】探索编程基础:深入理解分支与循环语句的奥秘

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C语言 “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;C语言入门 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀分支与循环语句 &#x1f4d2;1.…

颠仆流离学二叉树1 (Java版)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

Java 零基础入门学习(小白也能看懂!)

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…