为什么在 asp.net mvc 中使用数据库工厂?
Why use database factory in asp.net mvc?
最近我使用了 asp.net mvc,我在示例项目中看到正在使用数据库工厂 class。您如何向我解释为什么要使用它?
IDatabaseFactory class
public interface IDatabaseFactory : IDisposable
{
EFMVCDataContex Get();
}
数据库工厂class
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private EFMVCDataContex dataContext;
public EFMVCDataContex Get()
{
return dataContext ?? (dataContext = new EFMVCDataContex());
}
protected override void DisposeCore()
{
if (dataContext != null)
dataContext.Dispose();
}
}
这是一个 Abstract Factory 设计模式的例子。这个想法是创建一个接缝以提供 classes 之间的松散耦合,以便可以交换另一种类型的上下文,无论是出于测试目的还是为了扩展应用程序。
一般来说,工厂是一种管理短期依赖项(例如数据库连接)的方法。通常,框架公开了一种注入工厂实例的方法,然后框架可以基于接口(在本例中为 IDatabaseFactory)作为框架与框架用户之间的契约来使用它。该框架将具有如下所示的代码:
public interface ISomeService
{
void DoSomething();
}
public class SomeService()
{
private readonly IDatabaseFactory factory;
// The factory is injected through the constructor
public SomeService(IDatabaseFactory factory)
{
this.factory = factory;
}
public void DoSomething()
{
using (EFMVCDataContex context = this.factory.Get())
{
// Run a LINQ query here using the context
} // This bracket disposes the context
}
}
然后可以实例化服务,其生命周期比工厂创建的上下文长得多。更重要的是,上下文总是在这种情况下得到妥善处理。
现在,这样做的主要好处是您可以将 DatabaseFactory 替换为替代实现(通常称为 Liskov Substitution Principle):
public class MyDatabaseFactory : Disposable, IDatabaseFactory
{
private EFMVCDataContex dataContext;
public EFMVCDataContex Get()
{
return dataContext ?? (dataContext = new AlternateDataContext());
}
protected override void DisposeCore()
{
if (dataContext != null)
dataContext.Dispose();
}
}
假设 AlternateDataContext 继承(或实现)EFMVCDataContex,MyDatabaseFactory 可以与 DatabaseFactory 同类对换,而无需对 SomeService 进行任何更改。
MyDatabaseFactory 可以在构造函数中使用连接字符串进行编码,例如,为您提供一种连接到备用数据库的方法。
当然,这样做的另一大好处是创建可用于测试 DoSomething 方法的 IDatabaseFactory 的模拟实现。在单元测试中,SomeService(被测的 class)应该是唯一真正使用的 class,IDatabaseFactory 应该是一个模拟(可以通过手动编码 class,或使用模拟框架)。
最近我使用了 asp.net mvc,我在示例项目中看到正在使用数据库工厂 class。您如何向我解释为什么要使用它?
IDatabaseFactory class
public interface IDatabaseFactory : IDisposable
{
EFMVCDataContex Get();
}
数据库工厂class
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private EFMVCDataContex dataContext;
public EFMVCDataContex Get()
{
return dataContext ?? (dataContext = new EFMVCDataContex());
}
protected override void DisposeCore()
{
if (dataContext != null)
dataContext.Dispose();
}
}
这是一个 Abstract Factory 设计模式的例子。这个想法是创建一个接缝以提供 classes 之间的松散耦合,以便可以交换另一种类型的上下文,无论是出于测试目的还是为了扩展应用程序。
一般来说,工厂是一种管理短期依赖项(例如数据库连接)的方法。通常,框架公开了一种注入工厂实例的方法,然后框架可以基于接口(在本例中为 IDatabaseFactory)作为框架与框架用户之间的契约来使用它。该框架将具有如下所示的代码:
public interface ISomeService
{
void DoSomething();
}
public class SomeService()
{
private readonly IDatabaseFactory factory;
// The factory is injected through the constructor
public SomeService(IDatabaseFactory factory)
{
this.factory = factory;
}
public void DoSomething()
{
using (EFMVCDataContex context = this.factory.Get())
{
// Run a LINQ query here using the context
} // This bracket disposes the context
}
}
然后可以实例化服务,其生命周期比工厂创建的上下文长得多。更重要的是,上下文总是在这种情况下得到妥善处理。
现在,这样做的主要好处是您可以将 DatabaseFactory 替换为替代实现(通常称为 Liskov Substitution Principle):
public class MyDatabaseFactory : Disposable, IDatabaseFactory
{
private EFMVCDataContex dataContext;
public EFMVCDataContex Get()
{
return dataContext ?? (dataContext = new AlternateDataContext());
}
protected override void DisposeCore()
{
if (dataContext != null)
dataContext.Dispose();
}
}
假设 AlternateDataContext 继承(或实现)EFMVCDataContex,MyDatabaseFactory 可以与 DatabaseFactory 同类对换,而无需对 SomeService 进行任何更改。
MyDatabaseFactory 可以在构造函数中使用连接字符串进行编码,例如,为您提供一种连接到备用数据库的方法。
当然,这样做的另一大好处是创建可用于测试 DoSomething 方法的 IDatabaseFactory 的模拟实现。在单元测试中,SomeService(被测的 class)应该是唯一真正使用的 class,IDatabaseFactory 应该是一个模拟(可以通过手动编码 class,或使用模拟框架)。