抽象工厂模式

las*_*iya 47 architecture design-patterns abstract-factory c#-4.0

  1. C#中抽象工厂模式的好例子?
  2. C#中抽象工厂模式的优点是什么?
  3. 如何在抽象工厂模式中使用C#泛型?
  4. 如何用抽象工厂模式进行单元测试?

Sty*_*xxy 140

首先,我建议你阅读一下抽象工厂模式,例如这里.现在我将尝试解释为什么要使用这种模式.

通常,如果使用工厂模式,则将在工厂中创建对象.当您有一个给定类(或类)的多个实现时,会出现问题.现在,这些多个实现被分组.您将使用Abstract Factory pattern何时拥有工厂,但您希望将每组的对象创建分组.

好的,上面的解释可能不完全清楚,所以我举个例子.

假设您有一个包含数据代理的类库.数据代理为您提供访问和存储不同数据的方法.当然,有多种方式存储您的数据.例如:在数据库中,在XML文件中,在服务上,.对于这些可能的方法中的每一种,您都希望拥有数据代理.现在的问题是,你不希望有人将DataAgentA用于XML文件和DataAgentB用于数据库(假设我们有实体A和B).用户应该只使用一个存储引擎.

让我向您介绍抽象工厂模式.

您将确保用户无法直接实例化您的数据代理,但他们必须将这些数据代理从工厂中取出.(另一个优点是,当您使用例如数据库(EF)时,您可以进行内部连线以确保您的数据代理使用相同的上下文等.)我们如何实现这一目标?我们将数据代理的构造函数设置为"内部".除此之外,我们为每个存储引擎创建不同的工厂.现在,由于这些工厂都是这样做的,我们也有这些接口(就像我们的数据代理一样,因为它们都必须这样做,对吧!?).

下面我们有我们的接口.基本上这是工厂模式,但只是现在而不是关于,我们讨论的是接口.

public interface IAgentA 
{
    // Add some methods here!
}

public interface IAgentB
{
    // Add some methods here!
}

public interface IAgentFactory
{
    IAgentA CreateAgentA();
    IAgentB CreateAgentB();
}
Run Code Online (Sandbox Code Playgroud)

现在对于这两个代理,我们有两个可能的实现,一个用于XML,一个用于数据库存储(再次:这是一个示例,您可以拥有任意数量的实现类型).这些实现看起来像这样(见下文).请注意,我做了构造函数internal!这个代码块后面的部分需要这个.

public class AgentA_Xml : IAgentA
{
    internal AgentA_Xml()
    { /* Construction here */}

    // IAgentA method implementations
}

public class AgentB_Xml : IAgentB
{
    internal AgentB_Xml()
    { /* Construction here */}

    // IAgentB method implementations
}


public class AgentA_Database : IAgentA
{
    internal AgentA_Database()
    { /* Construction here */}

    // IAgentA method implementations
}

public class AgentB_Database : IAgentB
{
    internal AgentB_Database()
    { /* Construction here */}

    // IAgentB method implementations
}
Run Code Online (Sandbox Code Playgroud)

现在,因为构造函数是内部的.这导致您无法在程序集外部实例化这些类,这通常是您对这些情况所做的.现在我们必须创建我们的工厂.

public class XMLAgentFactory : IAgentFactory
{
    public IAgentA CreateAgentA()
    {
        return new AgentA_Xml();
    }

    public IAgentB CreateAgentB()
    {
        return new AgentB_Xml();
    }
}


public class DatabaseAgentFactory : IAgentFactory
{
    public IAgentA CreateAgentA()
    {
        return new AgentA_Database();
    }

    public IAgentB CreateAgentB()
    {
        return new AgentB_Database();
    }
}
Run Code Online (Sandbox Code Playgroud)

由于两个工厂都实现了IAgentFactory接口,用户可以轻松更改AgentFactory实现(如果他,在这种情况下,想要使用不同的存储引擎),而不必更改他写的任何其他代码(针对代理),只要他编程对接口(显然).

上面的解释有希望回答你的问题(1)和(2).

  1. C#中抽象工厂模式的好例子?
  2. c#中抽象工厂模式的优点是什么?

回答你的问题(3).

  1. 如何使用C#泛型与抽象工厂模式?

您仍然可以使用泛型,当您使用抽象工厂模式时,这不会改变任何位置.当然,您必须创建通用工厂方法(创建方法),但这不应该是任何问题.

回答你的问题(4).

  1. 如何使用抽象工厂模式进行单元测试?

就像你对任何其他类进行单元测试一样.只有一件事情会有所不同.

由于您可能还想测试类的构造函数(以及其他内部方法),因此需要使单元测试项目可以看到内部构造函数(方法)(并且您不希望更改internalpublic).通过AssemblyInfo.cs将以下行添加到项目文件(工厂和类所在的项目)中,可以轻松完成此操作:

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("My.UnitTest.Namespace")]
Run Code Online (Sandbox Code Playgroud)

您可以在MSDN上找到有关InternalsVisibleTo属性的更多信息(和备注).

我希望这样能回答你的问题.

  • 这个答案是人们有时谈论的那些隐藏的宝石之一.非常好解释.谢谢. (3认同)