抽象的工厂模式 [英] Abstract factory pattern

查看:194
本文介绍了抽象的工厂模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  1. C#中抽象工厂模式的好例子?

  2. C#中抽象工厂模式的优点是什么?

  3. 如何将C#泛型用于抽象工厂模式?

  4. 如何单元测试抽象工厂模式?


解决方案

,我建议您阅读有关抽象工厂模式的信息,例如此处。现在我将尝试解释为什么要使用此模式。



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



好吧,上面的解释可能不太清楚,所以我给你一个例子。



假设你有一个带有数据代理的类库。数据代理为您提供访问和存储不同数据的方法。当然,有多种方式来存储您的数据。例如:在数据库中,在XML文件中,通过服务,。对于每种可能的方式,您都希望有数据代理。现在的问题是,你不希望有人将DataAgentA用于XML文件与DataAgentB一起用于数据库(假设我们有实体A和B)。



让我来介绍一下抽象工厂模式。



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



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

  public interface IAgentA 
{
//在这里添加一些方法!
}

public interface IAgentB
{
//这里添加一些方法!
}

public interface IAgentFactory
{
IAgentA CreateAgentA();
IAgentB CreateAgentB();
}

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

  public class AgentA_Xml:IAgentA 
{
internal AgentA_Xml()
{/ *在这里构建* /}

// IAgentA方法实现
}

public class AgentB_Xml:IAgentB
{
internal AgentB_Xml()
{/ *在这里构建* /}

// IAgentB方法实现
}

b $ b public class AgentA_Database:IAgentA
{
internal AgentA_Database()
{/ *在这里构建* /}

// IAgentA方法实现
}

public class AgentB_Database:IAgentB
{
internal AgentB_Database()
{/ *在这里构建* /}

// IAgentB方法实现
}

现在构造函数是内部的。这导致您不能在程序集外部实例化这些类,这通常是使用这些类型的情况。现在我们要创建我们的工厂了。

  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();
}
}

因为两个工厂都实现了 IAgentFactory 接口,用户可以轻松地更改 AgentFactory 实现(如果他,在这种情况下,想使用不同的存储引擎),而不必



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



  1. C#中抽象工厂模式的好例子?

  2. 以及c#中抽象工厂模式的优点是什么?


回答您的问题(3)。



  1. li>


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



回答你的问题(4) p>



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


与单元测试任何其他类相同。只有一件事会有所不同。



因为你可能还想测试你的类的构造函数(或者其他内部方法),你需要使内部构造函数方法)对您的单元测试项目可见(并且您不想将 internal 更改为 public )。这很容易通过在你的项目(你的工厂和类所在的项目)的 AssemblyInfo.cs 文件中添加以下行:

  [assembly:System.Runtime.CompilerServices.InternalsVisibleTo(My.UnitTest.Namespace)] 
pre>

您可以在 MSDN



我希望这种回答你的问题。 / p>

  1. Good example for Abstract factory pattern in C#?
  2. What are the advantages of the Abstract factory pattern in C#?
  3. How to use C# generics with the Abstract factory pattern?
  4. How to unit test with the Abstract factory pattern?

解决方案

First of all, I would suggest you to read about the Abstract Factory pattern, for example here. Now I will try to explain why you would use this pattern.

Normally, if you use the Factory pattern, you will create objects in a Factory. The problem arises when you have multiple implementation of a given class (or classes). Now, those multiple implementations are grouped. You will use the Abstract Factory pattern when you have a factory, but you would like to group the creating of objects per group.

Okay, above explanation might not be completely clear, so I will give you an example.

Let's say you have a class library with data agents. Data agents provide you methods to access and store different data. Of course, there are multiple ways of storing your data. For example: in a database, in XML file, over a service, . For each of these possible ways, you would like to have data agents. Now the problem is, you don't want that someone uses the DataAgentA for XML files together with DataAgentB for database (let's assume that we have entities A and B). The user should use only one storage engine.

Let me introduce you the Abstract Factory pattern.

You will make sure that users cannot directly instantiate your Data Agents, but they will have to get these data agents out of a factory. (An extra advantage is, that when you use for example a database (EF), you can do internal wiring to make sure your Data Agents use the same context, etc.) How do we accomplish this? We set the constructor of our data agents to ´internal´. Apart from that, we create different factories for each storage engine. Now, since those factories all do the same, we also have these interfaced (just like our data agents, since they all have to do the same, right!?).

Below we have our interfaces. Basically this is the factory pattern, but only now instead of about classes, we are talking about interfaces.

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

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

public interface IAgentFactory
{
    IAgentA CreateAgentA();
    IAgentB CreateAgentB();
}

Now for the two agents, we have two possible implementations, one for XML and one for database storage (again: this is an example, you can have as many implementation types as you want). Those implementations would look like this (see below). Please note that I made the constructor internal! This is needed for the part that comes after this code block.

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
}

Now as the constructors are internal. This causes that you cannot instantiate those classes outside the assembly, which is generally what you do with these kind of cases. Now we have to create our factories.

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();
    }
}

Since both factories implement the IAgentFactory interface, the user can easily change of AgentFactory implementation (if he, in this case, wants to use a different storage engine) without having to change any other code he wrote (against the agents), as long as he programmed against the interfaces (obviously).

Above explanation hopefully answers your questions (1) and (2).

  1. Good example for Abstract factory pattern in C#?
  2. and what are advantages of Abstract factory pattern in c#?

Answering your question (3).

  1. How use C# generics with Abstract factory pattern?

You can still use generics, this doesn't change any bit when you use an Abstract Factory pattern. Of course, you will have to create generic factory methods (the create methods), but that shouldn't be any problem.

Answering your question (4).

  1. How does unit test with Abstract factory pattern?

Just the same as you would unit test any other class. Only one thing will be different.

Since you probably also want to test the constructor of your classes (and maybe other internal methods), you need to make the internal constructors (methods) visible to your unit test project (and you don't want to change the internal to public). This is easily done by adding the following line to your AssemblyInfo.cs file of your project (the project where your factory and classes are in):

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("My.UnitTest.Namespace")]

You can find more information (and remarks) about the InternalsVisibleTo attribute on MSDN.

I hope this kind of answers your question.

这篇关于抽象的工厂模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆