〇、简介

1、什么是抽象工厂模式?

一句话解释:

  提供一个接口,以创建一系列相关或相互依赖的抽象对象,而无需指定它们具体的类。(将一系列抽象类装进接口,一次接口实现,就必须实例化这一系列抽象类)

抽象工厂模式(Abstract Factory Pattern)是一种创建型模式。它用于创建一组相关对象的家族。强调的是一组对象之间的协作关系,而不是单个对象之间的依赖关系。抽象工厂类负责创建整个家族的对象的生命周期,并隐藏与实现有关的逻辑。

 一个比喻:(科目与课代表)

  语文和数学的课代表和副课代表,都按照抽象方法标准选好了,接下来同样的通过实现抽象类和接口标准,来选出两名物理课代表。当然,已经选出来的其他课代表,和本次选举无关联。

2、优缺点和使用场景

优点:

  • 可以降低系统中各个对象之间的耦合度。
  • 隔离了具体类的生产,使得客户并不需要知道什么被创建。
  • 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。

缺点:

  • 在增加新的产品方面比较困难,需要修改抽象工厂的接口,这样会导致所有的具体工厂也需要做出相应的修改。
  • 抽象程度高,可能会导致一些底层实现细节难以控制。

总之,抽象工厂模式能够有效地封装对象创建,但是扩展产品较为困难。它在软件开发中被广泛使用,特别是在跨平台软件开发中经常用到,使用时要注意系统对象的特点合理使用。

适用场景:

  • 一个系统要独立于它的产品的创建、组合和表示。
  • 一个系统要有多个产品系列中的一个来配置。
  • 要强调一系列相关的产品对象的设计,以便进行联合使用。
  • 提供一个产品类库,但只想显示它们的接口而不是实现。

实际使用场景举例:

  • 游戏开发:游戏中可能需要多种角色、武器、敌人等元素,它们之间可能存在关联性或依赖性,可以使用抽象工厂方法来快速构建游戏元素。
  • 数据库访问组件设计:不同数据库的连接、查询和数据存储方式可能存在差异,可以使用抽象工厂方法来创建不同数据库的访问组件、驱动和映射器。
  • 操作系统界面设计:不同操作系统的界面设计具有不同的特点,可以使用抽象工厂方法来创建不同操作系统下的控件。

总之,使用抽象工厂模式,都需要保证对象家族之间高内聚、松耦合,使得系统的设计和实现更加灵活和可扩展。

一、抽象工厂模式简单实现与扩展

通过两个抽象类 ProductA/ProductBBBB,实现四个具体产品类;在通过接口 IAbstractFactory,实现两个具体工厂的产品族 ConcreteFactory1/ConcreteFactory2。最后通过 Client 类注入工厂类的同时,创建产品的不同产品的实例,使客户端不用了解产品如何实例化,可以直接引用。

  1. // 抽象产品类。
  2. public abstract class ProductA
  3. {
  4. public abstract void OperationA();
  5. }
  6. public abstract class ProductBBBB
  7. {
  8. public abstract void OperationBBBB();
  9. }
  10. // 具体产品类,其中 ProductA1、ProductA2、ProductB1 和 ProductB2 分别代表不同的产品。
  11. public class ProductA1 : ProductA
  12. {
  13. public override void OperationA()
  14. {
  15. Console.WriteLine("ProductA1's operation.");
  16. }
  17. }
  18. public class ProductA2 : ProductA
  19. {
  20. public override void OperationA()
  21. {
  22. Console.WriteLine("ProductA2's operation.");
  23. }
  24. }
  25. public class ProductBBBB1 : ProductBBBB
  26. {
  27. public override void OperationBBBB()
  28. {
  29. Console.WriteLine("ProductBBBB1's operation.");
  30. }
  31. }
  32. public class ProductBBBB2 : ProductBBBB
  33. {
  34. public override void OperationBBBB()
  35. {
  36. Console.WriteLine("ProductBBBB2's operation.");
  37. }
  38. }
  39. // 抽象工厂接口,定义了各种不同产品族的生产方法。
  40. public interface IAbstractFactory
  41. {
  42. ProductA CreateProductA();
  43. ProductBBBB CreateProductBBBB();
  44. }
  45. // 每个具体工厂都能够生产特定的产品族。
  46. public class ConcreteFactory1 : IAbstractFactory
  47. {
  48. public ProductA CreateProductA()
  49. {
  50. return new ProductA1();
  51. }
  52. public ProductBBBB CreateProductBBBB()
  53. {
  54. return new ProductBBBB1();
  55. }
  56. }
  57. public class ConcreteFactory2 : IAbstractFactory
  58. {
  59. public ProductA CreateProductA()
  60. {
  61. return new ProductA2();
  62. }
  63. public ProductBBBB CreateProductBBBB()
  64. {
  65. return new ProductBBBB2();
  66. }
  67. }
  68. // 客户端代码使用抽象工厂来创建各种不同产品族的产品,而无需关心它们的实际实现。
  69. public class Client
  70. {
  71. private readonly ProductA _productA;
  72. private readonly ProductBBBB _productBBBB;
  73. public Client(IAbstractFactory factory)
  74. {
  75. _productA = factory.CreateProductA();
  76. _productBBBB = factory.CreateProductBBBB();
  77. }
  78. public void Run()
  79. {
  80. _productA.OperationA();
  81. _productBBBB.OperationBBBB();
  82. }
  83. }
  1. // 测试
  2. static void Main(string[] args)
  3. {
  4. Client client = new Client(new ConcreteFactory1());
  5. client.Run();
  6. Client client2 = new Client(new ConcreteFactory2());
  7. client2.Run();
  8. // 输出:
  9. // ProductA1's operation.
  10. // ProductBBBB1's operation.
  11. // ProductA2's operation.
  12. // ProductBBBB2's operation.
  13. }

下面我们尝试扩展出来一个新的产品 3:

  1. // 具体产品类
  2. public class ProductA3 : ProductA
  3. {
  4. public override void OperationA()
  5. {
  6. Console.WriteLine("ProductA3's operation.");
  7. }
  8. }
  9. public class ProductBBBB3 : ProductBBBB
  10. {
  11. public override void OperationBBBB()
  12. {
  13. Console.WriteLine("ProductBBBB3's operation.");
  14. }
  15. }
  16. // 具体工厂都能够生产特定的产品族
  17. public class ConcreteFactory3 : IAbstractFactory
  18. {
  19. public ProductA CreateProductA()
  20. {
  21. return new ProductA3();
  22. }
  23. public ProductBBBB CreateProductBBBB()
  24. {
  25. return new ProductBBBB3();
  26. }
  27. }

测试:

  1. static void Main(string[] args)
  2. {
  3. Client client = new Client(new ConcreteFactory1());
  4. client.Run();
  5. Client client2 = new Client(new ConcreteFactory2());
  6. client2.Run();
  7. Client client3 = new Client(new ConcreteFactory3());
  8. client3.Run();
  9. }

  

二、抽象工厂模式的结构

根据上一章节的示例代码,简单画一个 UML 图,如下:

  • AbstractFactory:声明一个创建抽象产品对象的操作接口。
  • ConcreteFactory:实现创建具体产品对象的操作。
  • AbstractProduct:为一类产品对象声明一个接口。
  • ConcreteProduct:定义一个将被相应的具体工厂创建的产品对象。实现了 IAbstractProduct 接口。
  • Client:仅使用由 AbstractFactory 和 AbstractProduct 类声明的接口。

通常在运行时创建一个 ConcreteFactory 类的实例,此实例具有 AbstractFactory  中全部定义的实现。当客户端需要创建不同的产品对象时,可以通过实现抽象工厂来创建具体工厂。

AbstractFactory  将产品对象的创建延迟到它的 ConcreteFactory 子类。

三、抽象工厂模式在 .net 框架中的实际应用

例如 DbProviderFactory,这个类位于 System.Data.Common.dll 程序集中,该类扮演抽象工厂模式中抽象工厂的角色,源码如下:

  1. // System.Data.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
  2. // System.Data.Common.DbProviderFactory
  3. using System.Data.Common;
  4. public abstract class DbProviderFactory
  5. {
  6. private bool? _canCreateDataAdapter;
  7. private bool? _canCreateCommandBuilder;
  8. public virtual bool CanCreateDataSourceEnumerator => false;
  9. public virtual bool CanCreateDataAdapter
  10. {
  11. get
  12. {
  13. if (!_canCreateDataAdapter.HasValue)
  14. {
  15. using DbDataAdapter dbDataAdapter = CreateDataAdapter();
  16. _canCreateDataAdapter = dbDataAdapter != null;
  17. }
  18. return _canCreateDataAdapter.Value;
  19. }
  20. }
  21. public virtual bool CanCreateCommandBuilder
  22. {
  23. get
  24. {
  25. if (!_canCreateCommandBuilder.HasValue)
  26. {
  27. using DbCommandBuilder dbCommandBuilder = CreateCommandBuilder();
  28. _canCreateCommandBuilder = dbCommandBuilder != null;
  29. }
  30. return _canCreateCommandBuilder.Value;
  31. }
  32. }
  33. public virtual DbCommand? CreateCommand()
  34. {
  35. return null;
  36. }
  37. public virtual DbCommandBuilder? CreateCommandBuilder()
  38. {
  39. return null;
  40. }
  41. public virtual DbConnection? CreateConnection()
  42. {
  43. return null;
  44. }
  45. public virtual DbConnectionStringBuilder? CreateConnectionStringBuilder()
  46. {
  47. return null;
  48. }
  49. public virtual DbDataAdapter? CreateDataAdapter()
  50. {
  51. return null;
  52. }
  53. public virtual DbParameter? CreateParameter()
  54. {
  55. return null;
  56. }
  57. public virtual DbDataSourceEnumerator? CreateDataSourceEnumerator()
  58. {
  59. return null;
  60. }
  61. }

下面是 SqlClientFactory.cs,继承了抽象类 DbProviderFactory,需要注意的是,此为引用程序集,即只包含元数据,不含可执行代码。如何通过工厂模式访问 SQLServer 数据库,可以参考官网示例: 获取 DbProviderFactory

点击查看 SqlClientFactory.cs
  1.  // System.Data.SqlClient, Version=4.6.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
  2. // System.Data.SqlClient.SqlClientFactory
  3. using System.Data.Common;
  4. using System.Data.SqlClient;
  5. /// <summary>Represents a set of methods for creating instances of the <see cref="N:System.Data.SqlClient" /> provider's implementation of the data source classes.</summary>
  6. public sealed class SqlClientFactory : DbProviderFactory
  7. {
  8. /// <summary>Gets an instance of the <see cref="T:System.Data.SqlClient.SqlClientFactory" />. This can be used to retrieve strongly typed data objects.</summary>
  9. public static readonly SqlClientFactory Instance;
  10. internal SqlClientFactory()
  11. {
  12. }
  13. /// <summary>Returns a strongly typed <see cref="T:System.Data.Common.DbCommand" /> instance.</summary>
  14. /// <returns>A new strongly typed instance of <see cref="T:System.Data.Common.DbCommand" />.</returns>
  15. public override DbCommand CreateCommand()
  16. {
  17. throw null;
  18. }
  19. /// <summary>Returns a strongly typed <see cref="T:System.Data.Common.DbCommandBuilder" /> instance.</summary>
  20. /// <returns>A new strongly typed instance of <see cref="T:System.Data.Common.DbCommandBuilder" />.</returns>
  21. public override DbCommandBuilder CreateCommandBuilder()
  22. {
  23. throw null;
  24. }
  25. /// <summary>Returns a strongly typed <see cref="T:System.Data.Common.DbConnection" /> instance.</summary>
  26. /// <returns>A new strongly typed instance of <see cref="T:System.Data.Common.DbConnection" />.</returns>
  27. public override DbConnection CreateConnection()
  28. {
  29. throw null;
  30. }
  31. /// <summary>Returns a strongly typed <see cref="T:System.Data.Common.DbConnectionStringBuilder" /> instance.</summary>
  32. /// <returns>A new strongly typed instance of <see cref="T:System.Data.Common.DbConnectionStringBuilder" />.</returns>
  33. public override DbConnectionStringBuilder CreateConnectionStringBuilder()
  34. {
  35. throw null;
  36. }
  37. /// <summary>Returns a strongly typed <see cref="T:System.Data.Common.DbDataAdapter" /> instance.</summary>
  38. /// <returns>A new strongly typed instance of <see cref="T:System.Data.Common.DbDataAdapter" />.</returns>
  39. public override DbDataAdapter CreateDataAdapter()
  40. {
  41. throw null;
  42. }
  43. /// <summary>Returns a strongly typed <see cref="T:System.Data.Common.DbParameter" /> instance.</summary>
  44. /// <returns>A new strongly typed instance of <see cref="T:System.Data.Common.DbParameter" />.</returns>
  45. public override DbParameter CreateParameter()
  46. {
  47. throw null;
  48. }
  49. }

下面再看一下 Oracle 工厂的实现,完全独立于其他数据库的工厂:

点击查看 OracleClientFactory.cs
  1. #region 程序集 Oracle.ManagedDataAccess, Version=4.122.21.1, Culture=neutral, PublicKeyToken=89b483f429c47342
  2. // C:\Users\zheng\.nuget\packages\oracle.manageddataaccess\21.10.0\lib\net462\Oracle.ManagedDataAccess.dll
  3. // Decompiled with ICSharpCode.Decompiler 7.1.0.6543
  4. #endregion
  5. using System;
  6. using System.Data.Common;
  7. using System.Security;
  8. using System.Security.Permissions;
  9. using OracleInternal.Common;
  10. namespace Oracle.ManagedDataAccess.Client
  11. {
  12. public sealed class OracleClientFactory : DbProviderFactory
  13. {
  14. public static readonly OracleClientFactory Instance = new OracleClientFactory();
  15. public override bool CanCreateDataSourceEnumerator => true;
  16. public override DbCommand CreateCommand()
  17. {
  18. if (ProviderConfig.m_bTraceLevelPublic)
  19. {
  20. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateCommand);
  21. }
  22. try
  23. {
  24. return new OracleCommand();
  25. }
  26. catch (Exception ex)
  27. {
  28. OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateCommand, ex);
  29. throw;
  30. }
  31. finally
  32. {
  33. if (ProviderConfig.m_bTraceLevelPublic)
  34. {
  35. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateCommand);
  36. }
  37. }
  38. }
  39. public override DbCommandBuilder CreateCommandBuilder()
  40. {
  41. if (ProviderConfig.m_bTraceLevelPublic)
  42. {
  43. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateCommandBuilder);
  44. }
  45. try
  46. {
  47. return new OracleCommandBuilder();
  48. }
  49. catch (Exception ex)
  50. {
  51. OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateCommandBuilder, ex);
  52. throw;
  53. }
  54. finally
  55. {
  56. if (ProviderConfig.m_bTraceLevelPublic)
  57. {
  58. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateCommandBuilder);
  59. }
  60. }
  61. }
  62. public override DbConnection CreateConnection()
  63. {
  64. if (ProviderConfig.m_bTraceLevelPublic)
  65. {
  66. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateConnection);
  67. }
  68. try
  69. {
  70. return new OracleConnection();
  71. }
  72. catch (Exception ex)
  73. {
  74. OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateConnection, ex);
  75. throw;
  76. }
  77. finally
  78. {
  79. if (ProviderConfig.m_bTraceLevelPublic)
  80. {
  81. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateConnection);
  82. }
  83. }
  84. }
  85. public override DbConnectionStringBuilder CreateConnectionStringBuilder()
  86. {
  87. if (ProviderConfig.m_bTraceLevelPublic)
  88. {
  89. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateConnectionStringBuilder);
  90. }
  91. try
  92. {
  93. return new OracleConnectionStringBuilder();
  94. }
  95. catch (Exception ex)
  96. {
  97. OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateConnectionStringBuilder, ex);
  98. throw;
  99. }
  100. finally
  101. {
  102. if (ProviderConfig.m_bTraceLevelPublic)
  103. {
  104. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateConnectionStringBuilder);
  105. }
  106. }
  107. }
  108. public override DbDataAdapter CreateDataAdapter()
  109. {
  110. if (ProviderConfig.m_bTraceLevelPublic)
  111. {
  112. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateDataAdapter);
  113. }
  114. try
  115. {
  116. return new OracleDataAdapter();
  117. }
  118. catch (Exception ex)
  119. {
  120. OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateDataAdapter, ex);
  121. throw;
  122. }
  123. finally
  124. {
  125. if (ProviderConfig.m_bTraceLevelPublic)
  126. {
  127. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateDataAdapter);
  128. }
  129. }
  130. }
  131. public override DbDataSourceEnumerator CreateDataSourceEnumerator()
  132. {
  133. if (ProviderConfig.m_bTraceLevelPublic)
  134. {
  135. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateDataSourceEnumerator);
  136. }
  137. try
  138. {
  139. return new OracleDataSourceEnumerator();
  140. }
  141. catch (Exception ex)
  142. {
  143. OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateDataSourceEnumerator, ex);
  144. throw;
  145. }
  146. finally
  147. {
  148. if (ProviderConfig.m_bTraceLevelPublic)
  149. {
  150. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateDataSourceEnumerator);
  151. }
  152. }
  153. }
  154. public override DbParameter CreateParameter()
  155. {
  156. if (ProviderConfig.m_bTraceLevelPublic)
  157. {
  158. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateParameter);
  159. }
  160. try
  161. {
  162. return new OracleParameter();
  163. }
  164. catch (Exception ex)
  165. {
  166. OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateParameter, ex);
  167. throw;
  168. }
  169. finally
  170. {
  171. if (ProviderConfig.m_bTraceLevelPublic)
  172. {
  173. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreateParameter);
  174. }
  175. }
  176. }
  177. public override CodeAccessPermission CreatePermission(PermissionState state)
  178. {
  179. if (ProviderConfig.m_bTraceLevelPublic)
  180. {
  181. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Entry, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreatePermission);
  182. }
  183. try
  184. {
  185. return new OraclePermission(state);
  186. }
  187. catch (Exception ex)
  188. {
  189. OracleException.HandleError(OracleTraceLevel.Public, OracleTraceTag.Error, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreatePermission, ex);
  190. throw;
  191. }
  192. finally
  193. {
  194. if (ProviderConfig.m_bTraceLevelPublic)
  195. {
  196. Trace.Write(OracleTraceLevel.Public, OracleTraceTag.Exit, OracleTraceClassName.OracleClientFactory, OracleTraceFuncName.CreatePermission);
  197. }
  198. }
  199. }
  200. }
  201. }

当然,诸如 Mysql、DB2 等类同。由此可见,当后续新增数据库时,只需对 DbProviderFactory 抽象工厂进行继承即可,对已实现的数据工厂毫无影响。

Abstract Factory 抽象工厂模式简介与 C# 示例【创建型1】【设计模式来了_1】的更多相关文章

  1. Java设计模式:Abstract Factory(抽象工厂)模式

    概念定义 抽象工厂(Abstract Factory)模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂模式中,系统的产品有多于一个的产品族(一个产品族里定义多个产品) ...

  2. c++ 设计模式9 (Abstract Factory 抽象工厂模式)

    5.2 抽象工厂模式 动机:在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作:同时,由于需求的变化,往往存在更多系列对象的创建工作. 代码示例: 实现利用数据库的业务逻辑,支持多数据库(Sq ...

  3. 设计模式(一): abstract factory抽象工厂模式 -- 创建型模式

    1.定义 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 2.适用场景 1.一个系统要独立于它的产品创建.组合和表示. 2.一个系统要由多个产品系列中的一个来配置. 3.当你要 ...

  4. 一天一个设计模式——Abstract Factory抽象工厂模式

    一.模式说明 前面学习了工厂方法(Factory Method)模式.在工厂方法模式中,在工厂方法模式中,父类决定如何生成实例,但并不决定所要生成的具体类,具体的处理交由子类来处理.这里学习的抽象工厂 ...

  5. Abstract Factory抽象工厂模式

    抽象工厂模式是是用一个超级工厂去创建其他工厂,简单点说就是工厂的父类,属于创建型模式. 目标:提供一个创建一组对象的方法,而无需指定它们具体的类(同工厂方法). 使用场景:系统的产品有多于一个的产品族 ...

  6. 面向对象设计模式纵横谈:Abstract Factory 抽象工厂模式(笔记记录)

         今天是设计模式的第二讲,抽象工厂的设计模式,我们还是延续老办法,一步一步的.演变的来讲,先来看看一个对象创建的问题. 1.如何创建一个对象 常规的对象创建方法: 这样的创建对象没有任何问题, ...

  7. Abstract Factory 抽象工厂模式

    提供一个创建一些列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂顾名思义就是对工厂的抽象,它提供了一组创建抽象产品对象的操作接口,我们实际使用的是抽象工厂的派生类,派生类中提供了操作的具 ...

  8. C#设计模式之四抽象工厂模式(AbstractFactory)【创建型】

    一.引言     写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了 ...

  9. C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】

    一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了解决[简 ...

  10. 2.设计模式-Abstract Factory 抽象工厂模式

    大神勿喷,不对的地方请指出来,学笔记而已. 解决的问题:应对多系列对象构建的变化或多系列(例如:崎岖的山路和平坦的马路属于一个系列) 不断的变化的创建. 使用场景:对象不变(比如有3个对象 " ...

随机推荐

  1. Python-趣味小程序

    1.效果 2.代码 import sys import time def print_act(word): #print('\n'+' '+'\r') #让光标回到行首 sys.stdout.writ ...

  2. Redis主从和哨兵搭建

    今天主要分享Redis主从架构和哨兵的搭建. 主从集群搭建 总共三个节点,一个主节点和两个从节点.都安装在一台机器上模拟主从集群,信息如下: IP PORT 角色 192.168.246.140 70 ...

  3. 第139篇:JS数组常用方法(map(),reduce(),foreach())

    好家伙,本篇为MDN文档数组方法的学习笔记 Array.prototype.reduce() - JavaScript | MDN (mozilla.org) 数组方法这块的知识缺了,补一下   1. ...

  4. 实例化对象 A a = new A();

    "new" 在Java中代表实例化的意思, A a = new A()代表实例化了一个对象a, 这个对象a属于A类. 可以认为A是一个抽象概念, 对象a是一个实体(存储于内存), ...

  5. C++ Primer 5th Edition, Chapter 2, Solutions

    Exercise 2.1 Questions What are the differences between int, long, long long, and short? Between an ...

  6. 2022-07-07:原本数组中都是大于0、小于等于k的数字,是一个单调不减的数组, 其中可能有相等的数字,总体趋势是递增的。 但是其中有些位置的数被替换成了0,我们需要求出所有的把0替换的方案数量:

    2022-07-07:原本数组中都是大于0.小于等于k的数字,是一个单调不减的数组, 其中可能有相等的数字,总体趋势是递增的. 但是其中有些位置的数被替换成了0,我们需要求出所有的把0替换的方案数量: ...

  7. 2021-11-05:摆动排序 II。给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序。你可以假设所有输入数组都可以

    2021-11-05:摆动排序 II.给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]- 的顺序.你可以假设所有 ...

  8. vue自定义组件——search-box

    pre { overflow-y: auto; max-height: 300px } github地址: https://github.com/lxmghct/my-vue-components 组 ...

  9. 洛谷P3368 【模板】树状数组 2-(区间修改,单点查询)

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 将某区间每一个数加上 x: 求出某一个数的值. 输入格式 第一行包含两个整数 N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含 N  ...

  10. 使用Mybatis生成树形菜单-适用于各种树形场景

    开发中我们难免会遇到各种树形结构展示的场景.比如用户登录系统后菜单的展示,某些大型购物网站商品的分类展示等等,反正开发中会遇到各种树形展示的功能,这些功能大概处理的思路都是一样的,所以本文就总结一下树 ...