Подтвердить что ты не робот

С# factory - это upcast a must?

Требуется ли шаблон С# factory?

Я хочу, чтобы Бог в библиотеке классов G создал Адама в библиотеке классов A, не делая G зависимым от A. Бог производит Адамс для потребления Евой в библиотеке классов E, и это хорошо, чтобы Ева могла знать и зависеть от Адама. (edit - этот образец продолжает улучшаться и улучшаться:)

Решение, о котором я мог думать, это наличие AdamFactory в A. Таким образом AdamFactory знает Адама и может легко его создать (возможно, просто вызвав конструктор Adam). Бог получает AdamFactory и может заказать его для CreateAdam.

Теперь, поскольку Богу не разрешено знать Адама, AdamFacotry CreateAdam должен вернуть объект, и для этого требуется, чтобы Eve поднял объект, возвращенный AdamFactory, на Адама.

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

P.S. - Не богохульство предназначалось, и я извиняюсь, если кому-то было больно. Казалось бы, лучше использовать Бога и Адама вместо Создателя и Создано, потому что два последних слова слишком похожи друг на друга.

Изменить: повторить предложение интерфейса. Предположим, что у Адама есть два метода: ProvideLove, ProvideFood и ProvideProtection (мы держим этот образец kis-safe:). Ева использует Адама для этих двух целей, но, конечно, Бог этого не делает. Итак, зачем предоставлять Богу знание о том, что AdamFactor возвращает то, что реализует IAdam, а не только объект? Я не понимаю!

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

Adam God.LoadAdam(AdamID theAdamID)
       var adam = new Adam(theAdamId, this)

Adam.Adam(AdamID theAdamID, God theGod)
      _god = theGod
      _mind  = theGod.LoadMind(theAdamId, this)

Mind God.LoadMind (AdamID theAdamID, Adam theAdam)
      var mind  = new Mind (theAdam)
      var mindId = new minId(theAdamId)
      mind.DeserializeFromFile(minId)

Mind.Mind (Adam theAdam)
      _adam = theAdam
4b9b3361

Ответ 1

Я не уверен, что полностью понимаю требования, но вот предложение:


//in assembly G
public abstract class HumanFactory<T>
{
    public abstract T CreateHuman();
}

//in assembly A
public class Adam { }
//in assembly A
public class AdamFactory : HumanFactory<Adam>
{
    public override Adam CreateHuman()
    {
        return new Adam();
    }
}

//in assembly G
public class God
{
    public T Create<T>(HumanFactory<T> factory)
    {
        return factory.CreateHuman();
    }
}

и использование:


//Somewhere in assembly E
Adam adam = new God().Create(new AdamFactory());

Ответ 2

Как насчет использования интерфейсов, чтобы Бог знал IAdam, или что-то вроде IHuman?

Ответ 3

Я думаю, вы могли бы использовать инъекцию зависимости. Попробуйте использовать контейнер с инверсией контроля (IoC), например Unity 2, StructureMap, или Замок Виндзора.

Ответ 4

Вы описываете абстрактный шаблон factory, хотя "детские" заводы (например, AdamFactory) обычно имеют что-то общее, поэтому вы 'd ожидать, что они будут создавать нечто большее, чем общий интерфейс, а не просто объект (см. ответ Davide)

Вы правы, чтобы беспокоиться о актерском составе, поскольку это свяжет Еву с реализацией Адама, которая побеждает цель factory (если вы действительно не используете его как строителя).

Вопрос в том, зачем вам нужен класс Бога?

Ответ 5

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

Итак, я бы не добавил лишние интерфейсы. Это нормально возвращать объект из десериализатора и затем вниз (например, BinaryFormatter, XmlSerializer).

Лучший способ - сделать ваш десериализатор общим.

Ответ 6

ОК, а как насчет разбрызгивания в некоторых дженериках здесь?

Пусть говорят, что Бог может принять Фабрики любого типа T, которые придерживаются следующего интерфейса:

interface IFactory  {
  Type CreatedType { get; }
  object Create();
}

Абстрактный класс для реализации этого может выглядеть следующим образом:

abstract class AbstractFactory<T> : IFactory {
  public Type CreatedType { get { return typeof(T); }
  public virtual object Create() {
    return innerCreate();
  }
  protected abstract override T innerCreate();
}

Теперь вы можете регистрировать фабрики с Богом:

God.RegisterFactory(new AdamFactory());

AdamFactory наследует от AbstractFactory<Adam>

Бог хранит свои фабрики в словаре, где ключ - это тип, возвращаемый интерфейсом IFactory

Теперь метод Create выглядит следующим образом:

God.Create<Adam>();

Бог заглядывает в свои фабрики, видит, что существует один тип type (T) общего метода, извлекает factory, вызывает создание и downcasts в T.

Как вы думаете?