Шаблон "фабрика" в C#: Как удостовериться, что экземпляр объекта может только быть создан классом фабрики?

Поместите это в мое уведомление о функции получения в моей службе уведомлений, и это решило проблему

 cancelNotification(sbn.getKey());
 notificationManager.cancel(sbn.getId());
85
задан Campi 6 May 2017 в 06:39
поделиться

9 ответов

Похож на Вас, просто хотят выполнить некоторую бизнес-логику прежде, чем создать объект - итак, почему Вы только не создаете статический метод в "BusinessClass", который делает весь грязный "myProperty", проверяющий работу, и делает конструктора частным?

public BusinessClass
{
    public string MyProperty { get; private set; }

    private BusinessClass()
    {
    }

    private BusinessClass(string myProperty)
    {
        MyProperty = myProperty;
    }

    public static BusinessClass CreateObject(string myProperty)
    {
        // Perform some check on myProperty

        if (/* all ok */)
            return new BusinessClass(myProperty);

        return null;
    }
}

Вызов его был бы довольно прост:

BusinessClass objBusiness = BusinessClass.CreateObject(someProperty);
56
ответ дан Ricardo Nolde 5 November 2019 в 05:56
поделиться

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

0
ответ дан Jim Arnold 5 November 2019 в 05:56
поделиться

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

public class Person
{
  internal Person()
  {
  }
}

public class PersonFactory
{
  public Person Create()
  {
    return new Person();
  }  
}

Однако я должен подвергнуть сомнению Ваш подход :-)

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

public class Person
{
  public Person(string firstName, string lastName)
  {
    FirstName = firstName;
    LastName = lastName;
    Validate();
  }
}
1
ответ дан Peter Morris 5 November 2019 в 05:56
поделиться

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

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

public MyBusinessObjectClass
{
    public string MyProperty { get; private set; }

    private MyBusinessObjectClass (string myProperty)
    {
        MyProperty  = myProperty;
    }

    pubilc static MyBusinessObjectClass CreateInstance (string myProperty)
    {
        if (MyBusinessLogicClass.ValidateBusinessObject (myProperty)) return new MyBusinessObjectClass (myProperty);

        return null;
    }
}

public MyBusinessLogicClass
{
    public static bool ValidateBusinessObject (string myProperty)
    {
        // Perform some check on myProperty

        return CheckResult;
    }
}

Таким образом, бизнес-объект не creatable непосредственно, и общедоступный метод проверки в бизнес-логике не причинит вреда также.

2
ответ дан User 5 November 2019 в 05:56
поделиться

Еще одна (легкая) опция состоит в том, чтобы сделать статический метод фабрики в классе BusinessObject и сохранить конструктора частным.

public class BusinessObject
{
    public static BusinessObject NewBusinessObject(string property)
    {
        return new BusinessObject();
    }

    private BusinessObject()
    {
    }
}
4
ответ дан Dan C. 5 November 2019 в 05:56
поделиться

Кроме того, что предложенный Jon, у Вас мог также или быть метод фабрики (включая проверку) быть статическим методом BusinessObject во-первых. Затем имейте частного конструктора, и все остальные будут вынуждены использовать статический метод.

public class BusinessObject
{
  public static Create (string myProperty)
  {
    if (...)
      return new BusinessObject (myProperty);
    else
      return null;
  }
}

, Но реальный вопрос - почему у Вас есть это требование? Действительно ли приемлемо переместить фабрику или метод фабрики в класс?

7
ответ дан Fabian Schmied 5 November 2019 в 05:56
поделиться

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

15
ответ дан Matt Hamilton 5 November 2019 в 05:56
поделиться

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

public class BusinessObject
{
  public static BusinessObjectFactory GetFactory()
  {
    return new BusinessObjectFactory (p => new BusinessObject (p));
  }

  private BusinessObject(string property)
  {
  }
}

public class BusinessObjectFactory
{
  private Func<string, BusinessObject> _ctorCaller;

  public BusinessObjectFactory (Func<string, BusinessObject> ctorCaller)
  {
    _ctorCaller = ctorCaller;
  }

  public BusinessObject CreateBusinessObject(string myProperty)
  {
    if (...)
      return _ctorCaller (myProperty);
    else
      return null;
  }
}

:)

49
ответ дан Fabian Schmied 5 November 2019 в 05:56
поделиться

Можно сделать конструктора частным, и фабрика вложенный тип:

public class BusinessObject
{
    private BusinessObject(string property)
    {
    }

    public class Factory
    {
        public static BusinessObject CreateBusinessObject(string property)
        {
            return new BusinessObject(property);
        }
    }
}

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

61
ответ дан Jon Skeet 5 November 2019 в 05:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: