Сохранение данных с использованием заводского шаблона? - PullRequest
11 голосов
/ 27 октября 2010

Я стал ближе знакомиться с Фабричным паттерном (вместе со Стратегическим паттерном) и с тем, какую большую пользу может принести паттерн. Однако я боролся со следующей ситуацией:

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

public class CarManager
{
    public static Car GetCarFromDatabase(int carId) { return new Car(); }

    public static void SaveCar(Car car) { }
}

Теперь я вижу, как у меня могут быть разные Factories, которые собирают машины для меня, будь то из базы данных или где угодно! Это замечательно! Итак, вот мои вопросы:

В1: Насколько я понимаю, Factories должен только строить объекты, это правильно? Если да, то как насчет моего второго вопроса?

В2: Если я следую заводскому шаблону при создании своих объектов, как мне сохранить свои объекты? Есть ли другой шаблон для этого или я не совсем понимаю Фабричный шаблон?

Ответы [ 5 ]

15 голосов
/ 27 октября 2010

Шаблон Factory должен помочь в создании объектов.Вот почему он относится к категории «Создание».Чтобы ответить на ваш первый вопрос, его не следует использовать для сохранения объектов.

Шаблон Репозиторий - это шаблон постоянства, который следует использовать для сохранения объектов в каком-либо механизме сохранения или извлечения данных измеханизм персистенции.На самом деле, по словам Мартина Фаулера, это корпоративный шаблон, к которому следует подходить иначе, чем типичный шаблон проектирования.

Размышляя над вопросом, вы хотите взглянуть на принцип S в SOLID * 1010.* в котором говорится, что класс должен нести единственную ответственность, что означает, что у него должна быть единственная причина для изменения.В этом случае, когда речь идет об объекте, который создает объекты, а также сохраняет (сохраняет их), у вас есть класс, у которого есть две причины для изменения.Теперь может показаться, что это может быть единственная ответственность, потому что репозиторий может извлекать и сохранять объекты в ваше приложение, а извлечение может выглядеть как фабрика (и часто это фабричный объект в репозитории), но в том, что вы описываетеу вашего объекта слишком много обязанностей.

3 голосов
/ 27 октября 2010

Завод не должен сохранять данные. Объект доступа к данным (DAO) или преобразователь таблиц был бы лучшей идеей.

2 голосов
/ 28 октября 2010

Все зависит от ваших потребностей и от того, как вы хотите делать вещи, шаблоны не являются стандартами, они поощряют повторное использование кода, шаблоны не берутся за камень. Итак, почему бы вам не использовать Factory Pattern для сохранения объектов ?. Вот как я использовал такой шаблон для решения проблемы чтения / записи данных из / в разные базы данных, возможно, это не лучшая форма использования шаблона, но в настоящее время он работает, расширяем, распределяется по слоям и почти это может понять каждый:

namespace Domain.App
{
    public class PresentationClass
    {
        private Collection<ISomeOutput> GetData(ISomeInput1 input)
        {   
            ServicesLogicContext logic = new ServicesLogicContext( (MyType) Identifier );
            return logic.GetSomeData(input) as Collection<ISomeOutput>;
        }
        private IMethodResult ExecuteSomeAction(ISomeInput2 input)
        {   
            ServicesLogicContext logic = new ServicesLogicContext( (MyType) Identifier);
            return logic.ExecuteSomeAction(input);
        }
    }
}   

namespace Domain.Logic
{
    public sealed class ServicesLogicContext : ServicesLogicContextBase
    {
        public IList<ISomeOutput> GetSomeData(ISomeInput1 input) 
        {
            DBServices services = DBServicesProvider.CreateServices(SomeIdentifier);
            return DBServicesProvider.GetSomeData(input);
        }
        public IMethodResult ExecuteSomeAction(ISomeInput2 input)
        {
            DBServices services = DBServicesProvider.CreateServices(SomeIdentifier);
            IMethodResult result = services.ExecuteSomeAction(input);
            return result;
        }
    }
}

namespace Domain.Data
{
    public abstract class DBServices : IServices
    {
        public virtual IList<ISomeOutput> GetSomeData(ISomeInput1 input)  {...}
        public virtual IMethodResult ExecuteSomeAction(ISomeInput2 input) {...}
    }

    public class DBServicesSpecific1 : DBServices
    {
        public override IList<ISomeOutput> GetSomeData(ISomeInput1 input)  {...}
        public override IMethodResult ExecuteSomeAction(ISomeInput2 input) {...}
    }

    public class DBServicesSpecific2 : DBServices
    {
        public override IList<ISomeOutput> GetSomeData(ISomeInput1 input)  {...}
        public override IMethodResult ExecuteSomeAction(ISomeInput2 input) {...}
    }

    public sealed class DBServicesProvider
    {
        public static DBServices CreateServices(MyType identifier)
        {
            DBServices result = null;       
            switch(identifier) 
            {
                case MyType.Specific1: result = new DBServicesSpecific1(); break;
                case MyType.Specific2: result = new DBServicesSpecific2(); break;       
            }
            return result;
        }
    }
}
1 голос
/ 27 октября 2010

Q1 - Да, шаблон Factory должен идеально использоваться для создания объектов. Таким образом, вы можете создать свой объект Car, используя фабричный шаблон.

Q2 - Для сохранения вашего автомобильного объекта не следует использовать заводской шаблон. Отсоедините объект Car от создания и сохранения объекта Car. И трудно предложить шаблон проектирования, чтобы сохранить объект вашего автомобиля без точного понимания требований. На мой взгляд, если вам просто нужно сохранить свои автомобильные объекты, то все, что вам, возможно, понадобится, это метод save в вашем классе менеджера автомобилей. Не переусердствуйте в использовании шаблонов дизайна.

1 голос
/ 27 октября 2010

В общем, я думаю, что вы подходите к этому с неправильной точки зрения.

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

Единственная проблема, которую вы упоминаете с кодом, который вы разместили, заключается в том, что юнит-тестирование нелегко,Одним из решений, позволяющих сделать классы более тестируемыми, является обращение их зависимостей.Итак, я бы начал смотреть, от каких других классов зависит этот класс, и начал бы делать эти инъекционные зависимости.В качестве отправной точки я бы порекомендовал вам ознакомиться с инверсией зависимостей / инверсией управления.

...