抽象工厂模式
- C#中抽象工厂模式的好例子?
- C#中抽象工厂模式的优点是什么?
- 如何在抽象工厂模式中使用C#generics?
- 如何用抽象工厂模式进行unit testing?
首先,我build议你阅读关于抽象工厂模式,例如这里 。 现在我将尝试解释为什么你会使用这种模式。
通常情况下,如果使用工厂模式,则将在工厂中创build对象。 当你有一个给定的类(或多个类)的多个实现时,问题就出现了。 现在,这些多个实现被分组。 有工厂时,您将使用“ Abstract Factory pattern
,但您希望将每个组的对象创build分组。
好吧,上面的解释可能不完全清楚,所以我会给你一个例子。
假设你有一个带有数据代理的类库。 数据代理为您提供访问和存储不同数据的方法。 当然,有多种方式来存储你的数据。 例如:在数据库中,在XML文件中,在服务上。 对于这些可能的方法中的每一种,您都希望拥有数据代理。 现在的问题是,您不希望有人使用DataAgentA for XML文件和DataAgentB for数据库(让我们假设我们有实体A和B)。 用户只能使用一个存储引擎。
让我给你介绍抽象工厂模式。
您将确保用户不能直接实例化您的数据代理,但他们将不得不从工厂中获取这些数据代理。 (另外一个好处是,当你使用例如数据库(EF)的时候,你可以做内部布线来确保你的数据代理使用相同的上下文等)。我们如何完成这个工作? 我们将数据代理的构造函数设置为“内部”。 除此之外,我们为每个存储引擎创build不同的工厂。 现在,由于这些工厂都做同样的事情,我们也有这些接口(就像我们的数据代理,因为他们都必须这样做,对!)。
下面我们有我们的接口。 基本上这是工厂模式,但现在只是现在,而不是关于类 ,我们正在谈论接口 。
public interface IAgentA { // Add some methods here! } public interface IAgentB { // Add some methods here! } public interface IAgentFactory { IAgentA CreateAgentA(); IAgentB CreateAgentB(); }
现在对于这两个代理,我们有两个可能的实现,一个用于XML,一个用于数据库存储(再次:这是一个例子,您可以有任意多的实现types)。 这些实现看起来像这样(见下文)。 请注意,我使构造函数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 }
现在作为build设者是内部的。 这导致你不能在程序集外部实例化这些类,这通常是你在这种情况下所做的。 现在我们必须创造我们的工厂。
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#generics与抽象工厂模式?
您仍然可以使用generics,当您使用抽象工厂模式时,这不会发生任何变化。 当然,你将不得不创buildgenerics工厂方法(创build方法),但这不应该是任何问题。
回答你的问题(4)。
- unit testing如何使用抽象工厂模式?
就像你会unit testing任何其他类一样。 只有一件事情会有所不同。
既然你可能也想testing你的类的构造函数(也许还有其他的内部方法),你需要让内部的构造函数(方法)对你的unit testing项目可见(并且你不想把internal
变成public
) 。 通过将以下行添加到项目的AssemblyInfo.cs
文件(您的工厂和类所在的项目)中,可以轻松完成此操作:
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("My.UnitTest.Namespace")]
您可以在MSDN上find关于InternalsVisibleTo属性的更多信息(和注释)。
我希望这种回答你的问题。