Вот еще одно решение в духе «просто потому, что ты не можешь означать, что должен» ...
Он отвечает требованиям сохранения приватности конструктора бизнес-объекта и помещения фабричной логики в другой класс. После этого он становится немного отрывочным.
В фабричном классе есть статический метод для создания бизнес-объектов. Он наследуется от класса бизнес-объектов для доступа к статическому защищенному методу конструирования, который вызывает закрытый конструктор.
Фабрика абстрактна, поэтому вы не можете создать ее экземпляр (потому что это также будет бизнес-объект, что было бы странно), и у него есть приватный конструктор, поэтому клиентский код не может быть выведен из него .
Что не помешает, так это клиентский код также , производный от класса бизнес-объекта и вызывающий защищенный (но не проверенный) метод статического построения. Или хуже, вызывая защищенный конструктор по умолчанию, который мы должны были добавить, чтобы сначала получить класс фабрики для компиляции. (Что, кстати, может быть проблемой для любого шаблона, который отделяет класс фабрики от класса бизнес-объекта.)
Я не пытаюсь предложить кому-то в здравом уме делать что-то подобное, но это было интересное упражнение. Впрочем, мое предпочтительное решение - использовать внутренний конструктор и границу сборки в качестве защиты.
using System;
public class MyBusinessObjectClass
{
public string MyProperty { get; private set; }
private MyBusinessObjectClass(string myProperty)
{
MyProperty = myProperty;
}
// Need accesible default constructor, or else MyBusinessObjectFactory declaration will generate:
// error CS0122: 'MyBusinessObjectClass.MyBusinessObjectClass(string)' is inaccessible due to its protection level
protected MyBusinessObjectClass()
{
}
protected static MyBusinessObjectClass Construct(string myProperty)
{
return new MyBusinessObjectClass(myProperty);
}
}
public abstract class MyBusinessObjectFactory : MyBusinessObjectClass
{
public static MyBusinessObjectClass CreateBusinessObject(string myProperty)
{
// Perform some check on myProperty
if (true /* check is okay */)
return Construct(myProperty);
return null;
}
private MyBusinessObjectFactory()
{
}
}