答案 0 :(得分:138)
首先,我建议您阅读有关抽象工厂模式的内容,例如here。现在我将尝试解释为什么要使用这种模式。
通常,如果使用Factory模式,则将在Factory中创建对象。当您有一个给定类(或类)的多个实现时,会出现问题。现在,这些多个实现被分组。当你有工厂时,你将使用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();
}
现在对于这两个代理,我们有两种可能的实现,一种用于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
}
现在因为构造函数是内部的。这导致您无法在程序集外部实例化这些类,这通常是您对这些情况所做的。现在我们必须创建我们的工厂。
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)。
- C#中抽象工厂模式的好例子?
- c#中的抽象工厂模式的优点是什么?
回答你的问题(3)。
- 如何将C#泛型与抽象工厂模式一起使用?
您仍然可以使用泛型,当您使用抽象工厂模式时,这不会改变任何位。当然,您必须创建通用工厂方法(创建方法),但这不应该是任何问题。
回答你的问题(4)。
- 如何使用抽象工厂模式进行单元测试?
就像你对任何其他类进行单元测试一样。只有一件事情会有所不同。
由于您可能还想测试类的构造函数(以及其他内部方法),因此需要使单元测试项目可以看到内部构造函数(方法)(并且您不希望更改{ {1}}到internal
)。通过将以下行添加到项目的public
文件(工厂和类所在的项目)中,可以轻松完成此操作:
AssemblyInfo.cs
您可以在MSDN上找到有关InternalsVisibleTo属性的更多信息(和备注)。
我希望这样能回答你的问题。