1

我正在使用基本的 3 层设计。出于灵活性(和测试)的目的,我希望数据层是抽象的,并在我的代码中指定具体的类。但是,我应该如何将它传递给我的业务对象。这是一个示例(伪代码):

abstract class IDataLayer
{
    PersonData GetPerson(int); //PersonData would be a row of data from a table for example
    JobData[] GetJobs(int);
    void UpdatePerson(PersonData);
}

class ConcreteDataLayerSQL : IDataLayer
{
...
}
class ConcreteDataLayerXML : IDataLayer
{
...
}

class PersonBAL
{
    void PersonBAL(personId)
    {
        //What goes here?
    }

    JobBAL[] GetJobs()
    {
       //What goes here?
    }
}
class Program
{
    static void Main()
    {
        person = new PersonBAL(1);
    }
}

那么问题来了,PersonBAL 怎么知道要使用哪个 ConcreteDataLayer 呢?我在几个选项之间考虑:

1:将具体的数据层传递给person。当您开始添加需要与数据层交互的新类时,这会变得很痛苦(比如 new PersonBAL(IDataLayer, int),然后是 new JobBAL(IDataLayer, int) 等)

2:创建一个包含要使用的数据层的静态对象(读取:全局变量)

还有其他想法吗?

4

3 回答 3

1

您要解决的问题是“依赖注入”。

假设这是 .NET 代码(您的伪代码语言看起来很像 C#),您可能想要研究像 Spring.NET 这样专为此类事情设计的框架。

于 2009-08-27T01:02:03.483 回答
0

我认为由于您列出的原因以及更改代码以使用不同的类将是容易出错的苦差事,因此在每个构造函数中传递类将具有挑战性。

依赖注入是 Spring 框架的核心。Spring 使用 XML 配置文件来描述类之间的关系。对于您的用例,您可以在配置中指定要实例化的特定类型,因此您只需进行一次更改即可切换实现。

Spring 是一个众所周知且经过测试的框架,但您当然不需要它来解决问题。您可以很好地为配置文件编写自己的代码。无论哪种方式,这本质上都是您提到的第二个选项的变体。

于 2009-08-27T16:23:33.747 回答
0

您可以在代码中放置一层间接层,这样您就永远不会直接构造 a PersonBAL而是PersonBALFactory使用 a 来构造PersonBAL实例。工厂依赖于通过构造函数传入的 IDataLayer(并且在您的应用程序启动时连接),您告诉工厂使用 PersonId 创建人员,它创建一个新的 PersonBAL 传递 ID 和IDataLayer。这样用户就不需要关心您使用的是哪个 IDataLayer,它是在启动时在应用程序配置中设置的,用户只需使用他们知道的信息请求新的 PersonBAL。

DI 框架将帮助您配置所有依赖注入,以便将正确的类型传递到构造函数中,并且一旦您拥有大量工厂,工厂(以及依赖于工厂的事物)的配置将变得自动化和简单或复杂的依赖图。

于 2010-11-25T11:24:38.770 回答