C# 创建型设计模式----工厂模式

news2024/10/26 15:03:12

1 、什么是工厂模式

简单来说就是由一个对象去生成不同的对象,工厂模式是用工厂方法代替new操作的一种模式。工厂方法封装了多个相关联类的new方法,每次实例化这些类的时候不需要new多次,只需要调用工厂类的对应方法即可实例化这些类,并且是通过使用一个共同的接口来指向新创建的对象。

工厂模式主要有三种类型:简单工厂(不介绍)工厂方法抽象工厂

2、工厂模式的作用

在创建对象时必然需要new该对象,当需要更改对象时,需要把项目中所有地方都修改一遍,这显然违背了软件设计的开闭原则。如果使用工厂来生成对象,那么我们只需要跟工厂打交道就可以了。如果要更新对象时,直接在工厂里更换即可。这就实现了对象解耦。

所以工厂模式主要用来解耦代码,将对象的创建和使用分离,使得代码更加灵活和可维护。

3、工厂方法

3.1、工厂方法模式的主要角色:

抽象工厂:在抽象工厂类中声明了工厂方法,用于返回一个产品。提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。

具体工厂:它是抽象工厂类的子类,实现了在抽象工厂中声明的工厂方法,完成具体产品的创建。并可由客户端调用,返回一个具体产品类的实例。

抽象产品:它是定义产品的接口,定义了产品的规范,描述了产品的主要特性和功能,是工厂方法模式所创建对象的公共父类

具体产品:它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间相互对应。

3.2、创建工厂方法

 抽象工厂:提供基类,通俗理解就是。有这么一个专门生产电蒸锅的集团架构(别问为什么是电蒸锅,因为我现在想买)。集团不提供锅,只提供流水线的基建,和产品的基本概念。

 /// <summary>
 ///抽象工厂--电蒸锅集团,专门生产各种电蒸锅
 /// </summary>
 public abstract class ElectricFactory
 {
     /// <summary>
     /// 声明获取抽象产品类方法(具体实现在其子类)--提供生产电蒸锅的流水线,流水线具体怎么生产,生产哪种集团不管
     /// </summary>
     /// <returns></returns>
     public abstract Electric GetElectric();
 }

具体工厂:继承抽象工厂--也就是具体的生产厂家,都是继承集团的流水线并定义里面具体的生产方式

/// <summary>
/// 具体工厂-美的流水线
/// </summary>
public class MDElectricFactory : ElectricFactory//美的属于该集团下的工厂
{
    /// <summary>
    /// 实现抽象方法,具体操作在里面
    /// </summary>
    /// <returns></returns>
    public override Electric GetElectric()//美的使用集团提供的流水线,集团提供什么,美的就能使用什么
    {
        Console.WriteLine("美的生产了一个锅");
        return new MDElectric();//返回具体产品-美的电蒸锅
    }
}
/// <summary>
/// 具体工厂-苏泊尔流水线
/// </summary>
public class SBRElectricFactory : ElectricFactory//苏泊尔属于该集团下的工厂
{
    /// <summary>
    /// 实现抽象方法,具体操作在里面
    /// </summary>
    /// <returns></returns>
    public override Electric GetElectric()//使用集团提供的流水线
    {
        Console.WriteLine("苏泊尔生产了一个锅");
        return new SBRElectric();//返回具体产品-苏泊尔电蒸锅
    }
}

抽象产品:集团告诉你这是电蒸锅,它有什么功能,下面的工厂生产的产品得有这个功能,至于功能怎么实现的集团不管。

/// <summary>
/// 抽象产品电蒸锅---集团定义的电蒸锅整个品类
/// </summary>
public abstract class Electric
{
    /// <summary>
    /// 抽象方法-定义电蒸锅有蒸东西的基本功能,具体怎么蒸就是下面的厂家决定。
    /// </summary>
    public abstract void Fun();

    /// <summary>
    /// 抽象产品提供拓展方法--子类产品非必须使用的,但可以有,就像有些电蒸锅有预约功能,有些没有。
    /// 而且最好是具体产品的共有的特性(公共方法),不建议是小众特性(仅适用于某个具体产品的方法),
    /// 例如电蒸锅的预约功能就很大众,可以有,
    /// 如果某个厂家要加一个烤盘功能,这就属于小众,放在具体厂家那里去实现更合适。
    /// </summary>
    public void AddFunction(string name)
    {
        Console.WriteLine($"{name}加了一个预约功能");
    }
}

具体产品:电蒸锅的蒸东西的功能具体实现方式

  /// <summary>
  /// 具体产品-美的电蒸锅
  /// </summary>
  public class MDElectric : Electric//这是美的电蒸锅,必须包含集团定义的电蒸锅的必备功能的同时也可以自己拓展
  {
      /// <summary>
      /// 具体的实现方法
      /// </summary>
      public override void Fun()
      {
          Console.WriteLine("美的电蒸锅蒸东西的功能是用大火蒸东西");
      }
  }
  /// <summary>
  /// 具体产品-苏泊尔电蒸锅
  /// </summary>
  public class SBRElectric : Electric//这是苏泊尔电蒸锅
  {
      public override void Fun()
      {
          Console.WriteLine("苏泊尔电蒸锅蒸东西的功能是用中火蒸东西");
      }
  }

使用:

private void WTBtn_Click(object sender, EventArgs e)
{
    ElectricFactory electric;//创建了一个电蒸锅集团。

    electric = new MDElectricFactory();//美的接入集团
    var DZG = electric.GetElectric();//美的使用集团生产线,定义生产线的具体流程并生产一个锅
    DZG.Fun();//这个锅实现具体的功能


    electric = new SBRElectricFactory();//苏泊尔接入集团
    var DZG1 = electric.GetElectric();//苏泊尔使用集团生产线,定义生产线的具体流程并生产一个锅
    DZG1.Fun();//这个锅实现具体的功能
    DZG1.AddFunction("苏泊尔");//看到电蒸锅大类(抽象产品)里可以加一个功能,让苏泊尔给这个锅加一个。
}

运行结果:

通过调用方式可以看出,不同产品的生产由原来的总工厂变为了各个分工厂去负责。

用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。

在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则。

这就是一整个工厂方法。当然这样看下来估计也是懵懂的不知道它有什么作用。

我再用文字尝试说明一下:

来设想你现在需要开发一个电商平台的订单模块,其中需要生成不同类型的订单,比如普通订单、促销订单、团购订单等。每个订单里面有很多的参数。

按照常规的方式,我们直接创建每个订单类,然后全部new出来即可, 这样就没必要创建什么工厂类了对吧?

假设订单类名是OrderA、OrderB、OrderC。有很多参数的情况下New就得

OrderA A=new OrderA(参数1,参数2,.....);

要使用里面具体方法还得

A.方法1();A.方法2();........

但是现在你有各种各样的订单,这些订单是你不同的同事去开发的。如果按你上面的做法,首先你需要知道每一个订单类的情况,你需要知道要成功new出一个具体的订单类需要哪些参数、需要执行哪些方法。但是这明显是不现实的,你没有时间去看源码,甚至看不到源码。

因为你的工作只是new出订单类并调用里面的方法罢了,而每个订单类具体怎么写,其实你不需要知道,这个时候每个订单类对应一个具体的工厂类,你只需要调用工厂里的创建产品方法就行了。

再者从单依职责原则,解耦合来考虑。如果按常规new OrderA的写法,你的同事某个订单类修改了,势必会导致你写的程序会直接创建报错,你就得跟着修改。但是使用了工厂方法,根本不会影响你,因为你不参与创建实例,你的程序也不需要任何的改动。你的同事如何修改订单类跟你也没关系。

嗯.....这样说不知道有没有说明白它的作用。。。

4、抽象工厂

上面工厂模式不管工厂怎么拆分抽象,都只是针对一类产品,直接生成实例,这些工厂只生产同种类产品。

但是抽象工厂模式不同,抽象工厂模式并不直接生成实例, 而是用于对产品类簇的创建。

通俗点来讲就是:简单工厂和工厂方法模式的工作是生产产品,那么抽象工厂模式的工作就是生产工厂的。

是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

抽象工厂的最大好处在于交换产品系列非常方便,只需要改变具体工厂即可使用不同的产品配置。

总的来说工厂方法模式一个工厂只生产一个产品,抽象工厂模式一个工厂生产多个产品,形成一个产品套餐,而多个工厂组成套餐系列。

4.1、抽象工厂模式的主要角色:

        抽象工厂:在抽象工厂类中声明了多个工厂方法,用于返回多个产品。提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。

  具体产品工厂:它是抽象工厂类的子类,实现了在抽象工厂中声明的多个工厂方法,完成多个具体产品的创建。

  抽象产品:它是定义一个产品的接口,定义了一个产品的规范,描述了一个产品的主要特性和功能。抽象工厂模式有多个抽象产品。

  具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

 4.2 创建方式

抽象工厂:有多少个系列就可以创建多少个抽象工厂类。本实例只创建了一个电器系列的工厂。里面可以有许多同系列的电器产品。

/// <summary>
///抽象工厂--电器集团,专门生产各种电器
/// </summary>
public abstract class ElectricFactory
{
    /// <summary>
    /// 生产电蒸锅
    /// </summary>
    /// <returns></returns>
    public abstract Electric GetElectric();
    /// <summary>
    /// 生产电饭煲
    /// </summary>
    /// <returns></returns>
    public abstract Rice GetRice();
}

具体工厂:同一系列可以创建多个具体的工厂,负责同一系列下的不同产品出的创建。本示例是电器下的电蒸锅和电饭煲,当然还可以电视机,烧水壶啥的。

 /// <summary>
 /// 具体工厂-美的工厂
 /// </summary>
 public class MDFactory : ElectricFactory//美的属于该集团下的工厂
 {
     public override Electric GetElectric()
     {
         Console.WriteLine("美的生产了一个电蒸锅");
         return new MDElectric();//返回具体产品-美的电蒸锅
     }

     public override Rice GetRice()
     {
         Console.WriteLine("美的生产了一个电饭煲");
         return new MDRice();
     }
 }
 /// <summary>
 /// 具体工厂-苏泊尔工厂
 /// </summary>
 public class SBRFactory : ElectricFactory//苏泊尔属于该集团下的工厂
 {
     /// <summary>
     /// 实现抽象方法,具体操作在里面
     /// </summary>
     /// <returns></returns>
     public override Electric GetElectric()//使用集团提供的流水线
     {
         Console.WriteLine("苏泊尔生产了一个电蒸锅");
         return new SBRElectric();//返回具体产品-苏泊尔电蒸锅
     }

     public override Rice GetRice()
     {
         Console.WriteLine("苏泊尔生产了一个电饭煲");
         return new SBRRice();
     }
 }

抽象产品:有多少个不同产品就创建多少个抽象产品类。

 /// <summary>
 /// 抽象产品电蒸锅---集团定义的电蒸锅整个品类
 /// </summary>
 public abstract class Electric
 {
     /// <summary>
     /// 抽象方法-定义电蒸锅有蒸东西的基本功能,具体怎么蒸就是下面的厂家决定。
     /// </summary>
     public abstract void Fun();

     /// <summary>
     /// 抽象产品提供拓展方法--子类产品非必须使用的,但可以有,就像有些电蒸锅有预约功能,有些没有。
     /// 而且最好是具体产品的共有的特性(公共方法),不建议是小众特性(仅适用于某个具体产品的方法),
     /// 例如电蒸锅的预约功能就很大众,可以有,
     /// 如果某个厂家要加一个烤盘功能,这就属于小众,放在具体厂家那里去实现更合适。
     /// </summary>
     public void AddFunction(string name)
     {
         Console.WriteLine($"{name}加了一个预约功能");
     }
 }

 /// <summary>
 /// 抽象产品-电饭煲
 /// </summary>
 public abstract class Rice
 {
     public abstract void Fun();
 }

具体产品:不同产品继承不同抽象类。

 /// <summary>
 /// 具体产品-美的电蒸锅
 /// </summary>
 public class MDElectric : Electric//这是美的电蒸锅,必须包含集团定义的电蒸锅的必备功能的同时也可以自己拓展
 {
     /// <summary>
     /// 具体的实现方法
     /// </summary>
     public override void Fun()
     {
         Console.WriteLine("美的电蒸锅蒸东西的功能是用大火蒸东西");
     }
 }
 /// <summary>
 /// 具体产品-苏泊尔电蒸锅
 /// </summary>
 public class SBRElectric : Electric//这是苏泊尔电蒸锅
 {
     public override void Fun()
     {
         Console.WriteLine("苏泊尔电蒸锅蒸东西的功能是用中火蒸东西");
     }
 }

 /// <summary>
 /// 具体产品-美的电饭煲
 /// </summary>
 public class MDRice : Rice//这是美的电饭煲
 {
     /// <summary>
     /// 具体的实现方法
     /// </summary>
     public override void Fun()
     {
         Console.WriteLine("美的电饭煲蒸东西的功能是用大火蒸东西");
     }
 }
 /// <summary>
 /// 具体产品-苏泊尔电饭煲
 /// </summary>
 public class SBRRice : Rice//这是苏泊尔电饭煲
 {
     public override void Fun()
     {
         Console.WriteLine("苏泊尔电饭煲蒸东西的功能是用中火蒸东西");
     }
 }

调用:

  private void WTBtn_Click(object sender, EventArgs e)
  {
      ElectricFactory electric;//创建了一个电器集团。

      electric = new MDFactory();//美的工厂
      var DZG = electric.GetElectric();//生产一个电蒸锅锅
      DZG.Fun();//这个锅实现具体的功能
      var DFB = electric.GetRice();//生产一个电饭煲
      DFB.Fun();


      //换个工厂
      electric = new SBRFactory();//苏泊尔工厂
      var DZG1 = electric.GetElectric();//生产一个电蒸锅锅
      DZG1.Fun();//这个锅实现具体的功能
      DZG1.AddFunction("苏泊尔");//看到电蒸锅大类(抽象产品)里可以加一个功能,让苏泊尔给这个锅加一个。
      var DFB1 = electric.GetRice();//生产一个电饭煲
      DFB1.Fun();

  }

上面实例可以看出创建一个工厂可以产出不同的产品。

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

缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

 END........................................................................

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

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

相关文章

2024年项目管理新风向:敏捷开发与瀑布开发,哪个更优?

一、项目管理的多样格局 2024 年&#xff0c;项目管理领域展现出丰富多样的格局。数字化趋势愈发明显&#xff0c;项目管理软件普及度不断提高&#xff0c;据相关资料显示&#xff0c;随着云计算、大数据等技术的成熟&#xff0c;项目管理软件将更加普及&#xff0c;实现项目信…

单片机_RTOS__架构概念

经典单片机程序 void main() {while(1){函数1&#xff08;&#xff09;&#xff1b;函数2&#xff08;&#xff09;&#xff1b;}} 有无RTOS区别 裸机 RTOS RTOS程序 喂饭&#xff08;&#xff09; {while&#xff08;1&#xff09;{喂一口饭&#xff08;&#xff09;;} } …

容灾与云计算概念

​​​​​​基础知识容灾备份——备份技术系统架构与备份网络方案-CSDN博客 SAN&#xff0c;是storage area network的简称&#xff0c;翻译过来就是存储区域网络。 顾名思义&#xff0c;SAN首先是一个网络&#xff0c;其次它是关于存储的&#xff0c;区域则是指服务器和存储资…

【C语言】控制台学生成绩管理系统

文章目录 C语言编程&#xff1a;学生成绩管理系统一、程序概述二、代码实现三、程序解释 C语言编程&#xff1a;学生成绩管理系统 在这篇文章中&#xff0c;我们将一起探讨如何使用C语言来创建一个简单的学生成绩管理系统。这个系统将允许用户输入学生数量、学号和成绩&#x…

气膜娱乐馆:科技与自然的完美结合—轻空间

在这片拥有独特滨海风光和丰富旅游资源的地方&#xff0c;气膜娱乐馆应运而生&#xff0c;为游客和当地居民打造了一个集运动、娱乐、亲子游乐和科技互动于一体的综合性室内娱乐体验。 灵活空间&#xff0c;舒适体验 气膜结构为娱乐馆提供了广阔的空间灵活性&#xff0c;使其能…

【Markdown速成】半小时入门Markdown教程(后缀.md文件详解)

目录 一.认识Markdown Markdown Typora 二.Typora设置 三.Markdown语法 1.标题 2.正文 2.1分割线 2.2删除线 2.3下划线 2.4斜体 2.5粗体 2.6斜粗体 2.7高亮 2.8字体属性&#xff08;大小及颜色&#xff09; 2.9对齐方式 2.10引用 3.列表 有序列表 无序列表 …

steam新品节!GameViewr远程随时随地手机平板玩主机游戏教程

Steam平台在10月14日迎来了新品节&#xff0c;你可以尝试即将推出的游戏的免费试用版&#xff0c;将他们加入愿望单&#xff0c;像是《迷失之径》《贪婪大地》《疯狂手机大亨》等等。不知道大家是否已经选择好自己心怡的游戏呢&#xff1f;要是你想随时随地体验steam新品节的游…

大一物联网要不要转专业,转不了该怎么办?

有幸在2014年&#xff0c;踩中了物联网的风口&#xff0c;坏消息&#xff0c;牛马的我&#xff0c;一口汤都没喝上。 依稀记得&#xff0c;当时市场部老大&#xff0c;带我去上海参加电子展会&#xff0c;印象最深的&#xff0c;一些物联网云平台&#xff0c;靠着一份精美PPT&a…

Visual studio 下载安装

1&#xff0c;Visual stutdio 网址 下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux 2&#xff0c;下划页面&#xff0c;点击 较早的下载 3&#xff0c;选择对应的版本进行下载

IDEA关联Tomcat——最新版本IDEA 2024

1.链接Tomcat到IDEA上 添加Tomcat到IDEA上有两种方式&#xff1a; 第一种&#xff1a; &#xff08;1&#xff09;首先&#xff0c;来到欢迎界面&#xff0c;找到左侧的Customize选项 &#xff08;2&#xff09;然后找到Build、Execution、Deployment选项 &#xff08;3&am…

LabVIEW中句柄与引用

在LabVIEW中&#xff0c;句柄&#xff08;Handle&#xff09; 是一种用于引用特定资源或对象的标识符。它类似于指针&#xff0c;允许程序在内存中管理和操作复杂的资源&#xff0c;而不需要直接访问资源本身。句柄用于管理动态分配的资源&#xff0c;如队列、文件、网络连接、…

使用query-string库出现错误Module parse failed: Unexpected token

环境 node v12query-string 9.1.0 报错信息 Failed to compile../node_modules/query-string/base.js 350:14 Module parse failed: Unexpected token (350:14) File was processed with these loaders:* ./node_modules/babel-loader/lib/index.js You may need an additio…

Hadoop:yarn的Rust API接口

今天头一次接触了yarn的Rust API接口&#xff0c;在本地搭建了集群&#xff0c;能够得到每个任务的详细信息。 (一)得到所有任务的所有信息命令&#xff1a; 默认是json格式&#xff0c;也可以指定xml的格式&#xff0c;如(curl --compressed -H "Accept: application/x…

个性化头像新选择:A1快速定制你的专属头像

个性化头像是彰显个人特色的绝佳方式&#xff0c;许多人为了表达自我&#xff0c;都会选择定制专属头像。然而&#xff0c;传统的定制头像服务往往价格不菲&#xff0c;且效果难以预测。幸运的是&#xff0c;AI绘画技术的发展为这一问题提供了解决方案。尽管许多AI绘画平台需要…

Windows server 2003服务器的安装

Windows server 2003服务器的安装 安装前的准备&#xff1a; 1.镜像SN序列号 图1-1 Windows server 2003的安装包非常人性化 2.指定一个安装位置 图1-2 选择好安装位置 3.启动虚拟机打开安装向导 图1-3 打开VMware17安装向导 图1-4 给虚拟光驱插入光盘镜像 图1-5 输入SN并…

使用 ASP.NET Core 8.0 创建最小 API

构建最小 API&#xff0c;以创建具有最小依赖项的 HTTP API。 它们非常适合需要在 ASP.NET Core 中仅包括最少文件、功能和依赖项的微服务和应用。 本教程介绍使用 ASP.NET Core 生成最小 API 的基础知识。 在 ASP.NET Core 中创建 API 的另一种方法是使用控制器。 有关在最小 …

数据结构 单调栈

应用情景 求当前元素 前面/后面&#xff0c;第一个比它 小/大 的元素的 值/下标/下标距离 优点 剔除重复寻路操作&#xff0c;将暴力 O(n^2) 优化到 O(n) 性质 从栈底开始&#xff0c;元素 单调递增/单调递减 单调性视具体情景而定 (找较大值还是较小值、找的方向) 思路…

提升数据处理效率:TDengine S3 的最佳实践与应用

在当今数据驱动的时代&#xff0c;如何高效地存储与处理海量数据成为了企业面临的一大挑战。为了解决这一问题&#xff0c;我们在 TDengine 3.2.2.0 首次发布了企业级功能 S3 存储。这一功能经历多个版本的迭代与完善后&#xff0c;逐渐发展成为一个全面和高效的解决方案。 S3…

语音提示器-WT3000A离在线TTS方案-打破语种限制/AI对话多功能支持

前言&#xff1a; TTS&#xff08;Text To Speech &#xff09;技术作为智能语音领域的重要组成部分&#xff0c;能够将文本信息转化为逼真的语音输出&#xff0c;为各类硬件设备提供便捷的语音提示服务。本方案正是基于唯创知音的离在线TTS&#xff08;离线本地音乐播放与在线…

【TFR-Net】基于transformer的鲁棒多模态情感分析特征重构网络

代码地址&#xff1a;TFR-Net/models at main thuiar/TFR-Net GitHub abstract&#xff1a; 提高对数据缺失的鲁棒性已经成为多模态情感分析&#xff08;MSA&#xff09;的核心挑战之一&#xff0c;MSA旨在从语言、视觉和声学信号中判断说话者的情感。在目前的研究中&#…