simple qué pattern patrones patron objetos metodo method fabrica entre ejemplo diseño diferencia conoces aparte design-patterns c#-4.0 architecture abstract-factory

design-patterns - qué - patrones de diseño fabrica de objetos



Patrón abstracto de fábrica (1)

Antes que nada, le sugiero que lea sobre el patrón Abstract Factory, por ejemplo here . Ahora intentaré explicar por qué usarías este patrón.

Normalmente, si usa el patrón de fábrica, creará objetos en una fábrica. El problema surge cuando tienes una implementación múltiple de una clase (o clases) determinada. Ahora, esas implementaciones múltiples están agrupadas. Utilizará el Abstract Factory pattern cuando tenga una fábrica, pero le gustaría agrupar la creación de objetos por grupo.

De acuerdo, la explicación anterior podría no estar completamente clara, así que les daré un ejemplo.

Supongamos que tiene una biblioteca de clases con agentes de datos. Los agentes de datos le proporcionan métodos para acceder y almacenar diferentes datos. Por supuesto, hay varias maneras de almacenar sus datos. Por ejemplo: en una base de datos, en un archivo XML, en un servicio,. Para cada una de estas formas posibles, le gustaría tener agentes de datos. Ahora el problema es que no desea que alguien use el DataAgentA para archivos XML junto con DataAgentB para la base de datos (supongamos que tenemos entidades A y B). El usuario debe usar solo un motor de almacenamiento.

Permítanme presentarles el patrón Abstract Factory.

Se asegurará de que los usuarios no puedan crear instancias directas de sus Agentes de datos, pero deberán sacar estos agentes de datos de una fábrica. (Una ventaja adicional es que cuando utiliza, por ejemplo, una base de datos (EF), puede realizar un cableado interno para asegurarse de que sus Agentes de Datos usan el mismo contexto, etc.) ¿Cómo logramos esto? Establecemos el constructor de nuestros agentes de datos en ''interno''. Además de eso, creamos diferentes fábricas para cada motor de almacenamiento. Ahora, dado que todas esas fábricas hacen lo mismo, también tenemos estas interfaces (al igual que nuestros agentes de datos, ya que todos tienen que hacer lo mismo, ¿no?).

A continuación tenemos nuestras interfaces. Básicamente, este es el patrón de fábrica, pero solo ahora en lugar de las clases , estamos hablando de interfaces .

public interface IAgentA { // Add some methods here! } public interface IAgentB { // Add some methods here! } public interface IAgentFactory { IAgentA CreateAgentA(); IAgentB CreateAgentB(); }

Ahora, para los dos agentes, tenemos dos implementaciones posibles, una para XML y otra para el almacenamiento de la base de datos (una vez más: este es un ejemplo, puede tener tantos tipos de implementación como desee). Esas implementaciones se verían así (ver más abajo). Tenga en cuenta que hice el constructor internal ! Esto es necesario para la parte que viene después de este bloque de código.

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 }

Ahora como los constructores son internos. Esto hace que no pueda crear instancias de esas clases fuera del ensamblado, que generalmente es lo que hace con este tipo de casos. Ahora tenemos que crear nuestras fábricas.

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

Dado que ambas fábricas implementan la interfaz IAgentFactory , el usuario puede cambiar fácilmente la implementación de AgentFactory (si él, en este caso, quiere usar un motor de almacenamiento diferente) sin tener que cambiar ningún otro código que haya escrito (contra los agentes), siempre y cuando programó contra las interfaces (obviamente).

La explicación anterior con suerte responde a sus preguntas (1) y (2).

  1. Buen ejemplo para el patrón abstracto de fábrica en C #?
  2. y ¿cuáles son las ventajas del patrón abstracto de fábrica en c #?

Respondiendo a tu pregunta (3).

  1. ¿Cómo se usan los genéricos C # con el patrón abstracto de fábrica?

Todavía puede usar genéricos, esto no cambia un poco cuando usa un patrón Abstract Factory. Por supuesto, tendrá que crear métodos genéricos de fábrica (los métodos de creación), pero eso no debería ser ningún problema.

Respondiendo a tu pregunta (4).

  1. ¿Cómo prueba la unidad con el patrón de fábrica abstracto?

Lo mismo que probarías en una unidad en cualquier otra clase. Solo una cosa será diferente.

Dado que probablemente también desee probar el constructor de sus clases (y tal vez otros métodos internos), debe hacer que los constructores internos (métodos) sean visibles para su proyecto de prueba unitario (y no desea cambiar el internal al public ) . Esto se hace fácilmente agregando la siguiente línea a su archivo AssemblyInfo.cs de su proyecto (el proyecto donde están su fábrica y sus clases):

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

Puede encontrar más información (y comentarios) sobre el atributo InternalsVisibleTo en MSDN .

Espero que este tipo de respuestas a su pregunta.

  1. Buen ejemplo para el patrón abstracto de fábrica en C #?
  2. ¿Cuáles son las ventajas del patrón abstracto de fábrica en C #?
  3. ¿Cómo usar los genéricos C # con el patrón abstracto de fábrica?
  4. ¿Cómo probar la unidad con el patrón abstracto de fábrica?