2016-01-26 2 views
0

У меня есть сценарий, в котором фабрика может создать дешевый или дорогой велосипед.Сокращение списка параметров фабрики

public class BikeFactory : IBikeFactory 
{ 
    public T GetInstance<T>(Guid userId, string bikeName, string bikeDescription, decimal value, DateTime shippingDate) where T : EntityBase 
    { 
     if (typeof(EntityBase).IsAssignableFrom(typeof(T)) && typeof(T) == typeof(ExpensiveBike)) 
     { 
      Information bikeInfo = new Information(bikeName,bikeDescription, value, shippingDate); 
      return (T)Activator.CreateInstance(typeof(T), userId, newIfo); 
     } 

     else if (typeof(EntityBase).IsAssignableFrom(typeof(T)) && typeof(T) == typeof(CheapBike)) 
     { 
      Information bikeInfo = new Information(bikeName,bikeDescription, value, shippingDate); 
      return (T)Activator.CreateInstance(typeof(T), userId, newIfo); 
     } 

     else return null; //for now 
    } 
} 

обе сущности CheapBike и ExpensiveBike провести ValueObject информацию, которая описывает их (хранит основную информацию о них). Как вы можете видеть список параметров некрасиво, но она есть, так что параметры приведены в Информационном consturctor

Information(bikeName, bikeDescription, vlaue, shippingDate) 

и конструктор CheapBike и ExpensiveBike (имеет идентификатор владельца велосипеда)

CheapBike(Guid owner, Information bikeInformation) // same for Expensive 

Я ищу способ, чтобы уменьшить число параметров, так что фабричный метод GetIstance() будет выглядеть следующим образом:

public T GetInstance<T>(Guid userId, Inforamtion bikeInfo) where T : EntityBase 

Вопрос:

  1. Должен ли я позволить клиенту построить информационный ValueObject через ValueObject завод и передать его в Bikefactory?

    VOfactory.GetInstance<Inforamtion>(infoDto.name, infoDto.description, infoDto.value, infoDto.shippingDate) 
    Efactory.GetInstance<CheapBike>(userId, bikeInfo) 
    
  2. Или просто позвольте клиенту построить объект Information ValueObject?

    Information bikeinfo = new Information(infoDto.name, infoDto.description, infoDto.value, infoDto.shippingDate); 
    
  3. Действительно ли это действительный подход?

+0

Это действительный подход, если ценность, которую вы получаете от него, стоит всей сложности. Почему родовая фабрика в первую очередь? – guillaume31

ответ

1

Должен ли я позволить клиенту построить информационный ValueObject через ValueObject завод и передать его в Bikefactory?

Это много заводов, я могу попытаться упростить его, предоставив перегрузку. Тот, который принимает объект Information или все параметры.

Тогда я позволил бы им экземпляр Information объекта без использования завода. Действительно, единственное преимущество фабрики в случае ValueObject заключается в создании объекта Information, что не полезно - для этого нужны конструкторы.

Или просто разрешите клиенту построить объект Information ValueObject?

Да, см. Выше объяснение.

Действительно ли это действительный подход?

Несомненно, до тех пор, пока завод используется правильно и выгодно для потребителя.

Пример использования:

var bikeInfo = new Information 
{ 
    Name = infoDto.name, 
    Description = infoDto.description, 
    Value = infoDto.value, 
    ShippingDate = infoDto.shippingDate 
} 
Efactory.GetInstance<CheapBike>(userId, bikeInfo); 

Или

Efactory.GetInstance<CheapBike>(userId, 
           infoDto.name, 
           infoDto.description, 
           infoDto.value, 
           infoDto.shippingDate); 
0

В этом случае я бы просто завернуть Parms в ваш объект DTO и пусть пользователь назначить их на создание. С учетом сказанного я снова посмотрю ваш дизайн, чтобы узнать, действительно ли завод действительно полезен в этом случае. Если оба объекта, возвращенные с фабрики, имеют одинаковые параметры, то почему у них есть несколько объектов?

void Main() 
{ 
    var bike = Factory.GetInstance<CheapBike>(() => new Information() 
    { 
     Name = "BMX", 
     Description = "..." 
    }); 

    //or 
    var bike = Factory.GetInstance<CheapBike>(GetInfo); 
} 

private Information GetInfo() 
{ 
    //do some logic to populate the info object to be passed 
    //into the constructor during factory initialization 
    return yourPopulatedInfoObject; 
} 

public static class Factory 
{ 
    public static T GetInstance<T>(Func<Information> func) where T : EntityBase 
    { 
     return (T)Activator.CreateInstance(typeof(T), func()); 
    } 
} 
+0

CheapBike и ExpensiveBike - разные объекты, потому что они ведут себя по-разному и имеют уникальные идентификаторы. Пример: ExpensiveBike имеет другие свойства, которые являются общими для каждого ExpensiveBike, такого как «SkeletonSymmetry», который задается методом 'DefineSkeletonSymetry()'. Такая симметрия изменяется в соответствии с предпочитаемыми владельцами рельефами. 'Владелец.DefineSkeletonSymetry («пустыня») ', но bouth CheapBike и ExpensiveBike должны иметь bikeInfo для того, чтобы быть сконструированным, а последний на Владельце может отрегулировать SkeletonSymmetry – user2153675

+0

@ user2153675, тогда ответ остался бы таким же. Если вы предоставляете функцию с возвращаемым типом объекта, который должен быть передан в конструктор ваших объектов, вы позволяете пользователю фабрики предоставлять свой собственный способ ввода этих значений. В моем примере я просто передаю простую функцию, которая возвращает объект DTO, но вы можете передать метод, который выполняет логику, чтобы динамически определять эти значения и все еще позволяет фабрике создавать экземпляр с необходимыми значениями. –

0

Какие проблемы вы пытаетесь решить, применив шаблон Factory к вашему дизайну здесь?

Вот два общих мотиваций использовать Factory:

  1. Чтобы уменьшить код клиента от выбора конкретной реализации
  2. абстрагироваться от сложного процесса

создания Насколько я могу скажите, что клиенты вашего завода передают конкретный тип, который им нужен, на заводе (ExpensiveBike или CheapBike), чтобы пустоты # 1.

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

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

«Я искал способ, чтобы уменьшить число параметров»

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

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

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

E.g.

var descriptor = new BikeDescriptor(name, description); 
var value = new Money(299.0, Currency.CAD); 
var bike = new CheapBike(id, descriptor, value, shippingDate); 
+0

Я уточнил свой домен в соответствии с вашими советами, помог много, но у меня есть еще один вопрос, который пришел к обзору кода со стороны. Если создание (такое же, как в вашем примере) велосипеда, должно выполняться на уровне приложения (службы), или если эта ответственность лежит на службе домена. Мне кажется, что он переусердствовал над построением службы домена, которая обрабатывает создание байка и вызывает его через интерфейс на уровне приложения. Аргумент заключался в том, что объекты домена должны быть построены в домене, а не на уровне приложения (службы). – user2153675

+0

@ user2153675 Методы прикладного обслуживания - это правильное место, чтобы переводить концепции, отличные от домена, в концепции домена большую часть времени. – plalx

+0

@ user2153675 Вы забыли свой вопрос? – plalx

Смежные вопросы