n-уровневое проектирование - лучший способ передать объект извлечения данных - PullRequest
1 голос
/ 27 августа 2009

Я использую базовый трехуровневый дизайн. В целях гибкости (и тестирования) я хотел, чтобы уровень данных был абстрактным и указывал конкретный класс в моем коде. Но как мне передать это своим бизнес-объектам? Вот пример (псевдокод):

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: передать конкретный слой данных человеку. Это становится проблемой, когда вы начинаете добавлять новые классы, которые должны взаимодействовать со слоем данных (что-то вроде нового PersonBAL (IDataLayer, int), затем нового JobBAL (IDataLayer, int) и т. Д.)

2: создание статического объекта, который содержит используемый слой данных (Чтение: глобальная переменная)

Есть еще идеи?

Ответы [ 3 ]

1 голос
/ 27 августа 2009

Проблема, которую вы пытаетесь решить, это «внедрение зависимостей».

Предполагая, что это код .NET (ваш язык псевдо-кода очень похож на C #), вы можете захотеть взглянуть на среду, подобную Spring.NET, которая предназначена для такого рода вещей.

0 голосов
/ 25 ноября 2010

вы можете добавить слой косвенности в ваш код, чтобы вы никогда не создавали PersonBAL напрямую, вместо этого у вас есть PersonBALFactory, который вы используете для создания своих PersonBAL экземпляров. У фабрики есть зависимость от IDataLayer, который передается через конструктор (и который подключается во время запуска вашего приложения), и вы указываете фабрике создать человека с помощью PersonId, и он создает новый PersonBAL, передающий идентификатор и IDataLayer. Таким образом, пользователю не нужно беспокоиться о том, какой IDataLayer вы используете, он настраивается в конфигурации приложений во время запуска, пользователь просто запрашивает новый PersonBAL, используя информацию, которую он знает.

Инфраструктуры DI помогут вам настроить все внедрение зависимостей так, чтобы правильные типы передавались в конструкторы, и сделают настройку фабрик (и вещей, которые зависят от фабрик) автоматической и более простой, когда у вас много фабрик или сложных графов зависимостей.

0 голосов
/ 27 августа 2009

Я думаю, что передача класса в каждом конструкторе была бы сложной по той причине, что вы перечислили, и потому что изменение кода для использования другого класса было бы подвержено ошибкам.

Внедрение зависимостей лежит в основе среды Spring. Spring использует файлы конфигурации XML для описания отношений между классами. Для вашего случая использования вы можете указать конкретный тип, который вы хотите создать в конфигурации, поэтому вам нужно всего лишь внести одно изменение, чтобы переключить реализации.

Spring - хорошо известная и проверенная среда, но, конечно, она не нужна для решения проблемы. Вы могли бы очень хорошо написать свой собственный код для файлов конфигурации. В любом случае, это, по сути, вариант второй упомянутой вами опции.

...