为什么要在C#中使用抽象工厂模式 [英] Why use Abstract factory pattern in C#

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

问题描述

大多数的定义说:


  

这是抽象工厂提供了一个
  界面,用于创建家庭
  不指定相关对象
  它们具体的类


有什么用抽象工厂模式,因为我们可以通过建立具体的类本身的对象实现的任务。为什么我们有一个创建具体类的对象的工厂方法?

请给我提供任何现实生活中的例子,我必须实现abstractFactory格局?


解决方案

首先,我建议你阅读有关抽象工厂模式,例如的此处。现在,我会尽量解释为什么要使用这种模式。

通常情况下,如果你使用工厂模式,您将创建一个工厂对象。当你有多个实现给定类(或类)的问题出现了。现在,这些多个实现分组。您将使用 Abstract Factory模式当你有一个工厂,但是你想组每组对象的创建。

好吧,上面的说明可能不是完全清楚,所以我会给你一个例子。

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

让我给你介绍抽象工厂模式。

您将确保用户不能直接实例化数据代理,但是他们必须要得到这些数据代理了工厂。 (一个额外的好处是,当你使用例如数据库(EF),你可以做内部布线,以确保您的数据代理使用相同的上下文等),我们如何做到这一点?我们设定我们的数据代理的构造函数'internal'。除此之外,我们为每个存储引擎不同的工厂。现在,因为这些工厂都做同样的,我们也有这些接口(就像我们的数据代理,因为他们都做同样的,对吧!?)。

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

 公共接口IAgentA
{
    //添加一些方法在这里!
}公共接口IAgentB
{
    //添加一些方法在这里!
}公共接口IAgentFactory
{
    IAgentA CreateAgentA();
    IAgentB CreateAgentB();
}

现在的二级代理,我们有两个可能的实现,一个用于XML,一个用于数据库存储(再次:这是一个例子,你可以根据需要有尽可能多的实现类型)。这些实现看起来像这样(见下文)。请注意,我在构造内部!这是需要为此code座后自带的部分。

 公共类AgentA_Xml:IAgentA
{
    内部AgentA_Xml()
    {/ *这里建设* /}    // IAgentA方法实现
}公共类AgentB_Xml:IAgentB
{
    内部AgentB_Xml()
    {/ *这里建设* /}    // IAgentB方法实现
}
公共类AgentA_Database:IAgentA
{
    内部AgentA_Database()
    {/ *这里建设* /}    // IAgentA方法实现
}公共类AgentB_Database:IAgentB
{
    内部AgentB_Database()
    {/ *这里建设* /}    // IAgentB方法实现
}

现在的构造函数是内部的。这会导致你不能实例汇编,一般你这类案件做什么是外面那些类。现在,我们要创造我们的工厂。

 公共类XMLAgentFactory:IAgentFactory
{
    公共IAgentA CreateAgentA()
    {
        返回新AgentA_Xml();
    }    公共IAgentB CreateAgentB()
    {
        返回新AgentB_Xml();
    }
}
公共类DatabaseAgentFactory:IAgentFactory
{
    公共IAgentA CreateAgentA()
    {
        返回新AgentA_Database();
    }    公共IAgentB CreateAgentB()
    {
        返回新AgentB_Database();
    }
}

由于两个工厂实施 IAgentFactory 接口,用户可以轻松地更改 AgentFactory 的实施(如果他在这种情况下,希望他对编程接口(显然)。

要使用不同的存储引擎),而无需更改任何其他code他写了(对代理商),只要

以上解释希望回答您的问题(1)和(2)。


  

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

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

  4.   

回答你的问题(3)。


  

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

  2.   

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

回答你的问题(4)。


  

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

  2.   

其实都一样,你会单元测试的其他类。只有一件事会有所不同。

因为你很可能也想测试你的类(也许其他的内部方法)的构造函数,你需要看到的内部构造(方法)到你的单元测试项目(你不想改变内部公共)。

:这很容易通过添加以下行到您的项目(该项目在您的工厂和类是)你的的AssemblyInfo.cs 文件来完成

  [汇编:System.Runtime.CompilerServices.InternalsVisibleTo(My.UnitTest.Namespace)]

您可以找到关于<一的InternalsVisibleTo属性的详细信息(和备注) href=\"http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx\">MSDN.

我希望这样的回答你的问题。

Most of the definition says:

An abstract factory provides an interface for creating families of related objects without specifying their concrete classes

What is the use of Abstract Factory Pattern as we can achieve the task via creating object of concrete class itself. Why do we have a factory method that creates object of Concrete class?

Please provide me any real life example where I must implement abstractFactory 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.

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

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