65.9K
CodeProject 正在变化。 阅读更多。
Home

使用泛型实现工厂模式

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.25/5 (8投票s)

2011 年 1 月 12 日

CPOL

3分钟阅读

viewsIcon

70766

downloadIcon

400

使用泛型实现工厂模式

引言

本文揭示了使用泛型的设计模式的一些良好用法。试想一下,如果这些设计模式使用.NET中的泛型来实现,将会产生奇效。您可以创建自己的设计模式类库,然后在任何项目中重复使用。我将展示在.NET中使用泛型的工厂设计模式。

背景

对于那些不了解工厂设计模式的人,请参考GOF的这篇文章,链接如下

Using the Code

现在让我们开始编写一些代码。首先,我将向您展示不使用泛型的工厂模式的实现。然后,我们将使用泛型来更改同一个工厂模式,您将会看到区别。因此,我们首先创建两个简单的类,即ReportGeneratorReportAnalyser,它们共享一个公共接口实现IActivity

注意:我仅以ReportGeneratorReportAnalyser类为例。

public interface IDBActivity 
{
 void Process();
}

public class Enumeration
{
    public enum ModuleName
    {
        ReportGenerator = 1,
        ReportAnalyser = 2
    }
}
    		
public class ReportGenerator : IActivity 
{
  public void Process()
  {
    // Do some coding here ...
  }	                               
}

public class ReportAnalyser : IActivity 
{
  public void Process()
  {
     // Do some coding here ...
  }						                                
}        

现在开始实现工厂模式。为了实现这一点,让我们创建一个类FactoryClass

public class FactoryClass
{
  public static IActivity CreateInstance(Enumeration.ModuleName enumModuleName)
  {
     IActivity objActivity = null;
     
     switch (enumModuleName)
     {
          case Enumeration.ModuleName.ReportGenerator:
                 objActivity = new ReportGenerator(); 
                 break;
          case Enumeration.ModuleName.ReportAnalyser:
                 objActivity = new ReportAnalyser();
                 break;
          default:
                 break;
     }
     return objActivity;
  }
}

从上面的代码中,我们根据传递的enum值创建一个ReportGeneratorReportAnalyser类的实例,并将其分配给IActivity对象。因此,当客户端调用CreateInstance方法时,它将只接收IActivity对象,而不是ReportGeneratorReportAnalyser对象。

这就是我们所说的工厂模式的核心,客户端创建ReportGeneratorReportAnalyser的对象,而无需指定对象的具体类。下面的代码片段显示了客户端如何通过调用我们的FactoryClassCreateInstance()方法来使用工厂模式。

private void btnProcess_Click(object sender, EventArgs e)
{	
    IActivity objActivity = null;

    objActivity = FactoryClass.CreateInstance(Enumeration.ModuleName.ReportGenerator);
    objActivity.Process();
}

现在是本文的重要部分,我将向您展示如何在工厂模式中使用泛型。好的,让我们首先创建一个新的Windows类库项目,并将其命名为DesignPatterns。在该项目中,创建一个新类,并将其命名为FactoryPattern
在该类中,请编写如下代码

public class FactoryPattern <K,T> 
        where T : class, K, new()
{
    public static K CreateInstance()
    {
        K objK;

        objK = new T();

        return objK;            
    }
}	  	

您可能想知道这是什么意思?? :-)。好的,我将向您解释这个概念。在这里,我使用泛型创建了FactoryPattern类。它接受两个参数,即“K”和“T”。T参数具有“where”约束,该约束表明T应该是一个类,应该从K继承,并且可以创建它的实例。 呃...太多的概念。让我们分析这行代码where T : class, K, new()

  • where T:- 表示您希望在客户端传递T作为类型参数时实现一些约束
  • class:- 表示传递的T参数应该是一个类
  • K:- 表示传递的T参数(它是一个类)应该始终从K类型参数继承
  • new():- 表示您可以在FactoryPattern类中创建传递的T参数的实例

我相信这很有意义,现在事情变得更清楚了。所以现在我知道您脑海中会浮现的问题是如何将此类应用到工厂模式实现中?您只需要对FactoryClass中编写的代码进行一些更改。
请找到下面的代码片段,这将使事情更加清晰

public class FactoryClass
 {
   public static IActivity CreateInstance(Enumeration.ModuleName enumModuleName)
   {
      IActivity objActivity = null;
      
      switch (enumModuleName)
      {
           case Enumeration.ModuleName.ReportGenerator:
                  /* Old coding ...
                  objActivity = new ReportGenerator(); 
                  */
                  objActivity = FactoryPattern<IActivity, 
			ReportGenerator>.CreateInstance();
                  break;
           case Enumeration.ModuleName.ReportAnalyser:
                  /* Old coding ...
                  objActivity = new ReportAnalyser();
                  */
                  objActivity = FactoryPattern<IActivity, 
				ReportAnalyser>.CreateInstance();
                  break;
           default:
                  break;
      }
      return objActivity;
   }
 }   

这就是将泛型与工厂模式一起使用。现在您可以弄清楚这行代码的含义where T : class, K, new()了吗?
ReportGenerator是一个类。它从IActivity接口继承。您可以创建ReportGenerator类的实例。由于您使用泛型创建了FactoryPattern类,并且对象的构造逻辑都位于中心点,因此您现在可以在所有未来的项目中使用您的
FactoryPattern类。您不必考虑/担心对象的创建,只需传递适当的参数,对象就会在FactoryPattern类中创建。

想想您可以使用泛型实现的其他设计模式...听起来很有挑战性!!

我希望这篇文章对您有所帮助。由于这是我的第一篇文章,我可能犯了一些错误,如果是这样,请纠正它。
您可以下载源代码。它是用.NET 3.5开发的。

© . All rights reserved.