Сохранение данных с помощью шаблона Factory?

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

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

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

    public static void SaveCar(Car car) { }
}

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

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

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

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

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

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;
        }
    }
}

Ответ 4

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

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

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

Ответ 5

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

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