Фабрика C # - выскочка обязательна? - PullRequest
18 голосов
/ 02 февраля 2011

Требует ли шаблон фабрики C # апскейтинга?

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

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

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

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

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

Редактировать: Re интерфейс подсказки.Давайте предположим, что у Адама есть два метода: ProvideLove, ProvideFood и ProvideProtection (мы держим этот пример в безопасности).Ева использует Адама для этих двух целей, но, конечно, Бог этого не делает.Так зачем сообщать Богу, что 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

Ответы [ 6 ]

9 голосов
/ 02 февраля 2011

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


//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());
1 голос
/ 02 февраля 2011

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

1 голос
/ 02 февраля 2011

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

0 голосов
/ 02 февраля 2011

Ладно, а как насчет обсыпки некоторых дженериков здесь?

Допустим, Бог может принять фабрики любого типа 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

Метод создания теперь выглядит так:

God.Create<Adam>();

Бог смотрит на его фабрики, видит, что есть один для typeof (T) универсального метода, получает фабрику, вызывает create и понижает до T.

Что вы думаете?

0 голосов
/ 02 февраля 2011

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

Так что я бы не стал добавлять ненужные интерфейсы.Можно возвращать объект из десериализатора и затем возвращать его вниз (например, BinaryFormatter, XmlSerializer).

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

0 голосов
/ 02 февраля 2011

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

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

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

...