Целесообразность фабричного метода

251
16 сентября 2021, 17:10

Допустим, есть некоторая иерархия классов, где каждый последующий класс наследуется от предыдущего.

Мне хотелось бы, что бы каждый класс имел свой статический метод Parse, который бы принимал строку и возвращал построенный объект.

Как я понимаю, переопределить статический метод в классах потомках нельзя, а можно только через перекрытие с и спользованием new...

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

Answer 1

Попробую ответить, отталкиваясь от термина Фабричный метод, который вы использовали.

Предположим, что у вас есть некая сложная иерархия:

interface IType;
class Type : IType;
class SecondType : Type;
class ThirdType : IType;

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

class TypeProcessor<T> where T : IType
{
  public void Process(string input)
  {
    var someObject = T.Parse(input);
    Console.WriteLine(this.ProcessInternal(someObject));
  }
  protected string virtual ProcessInternal(T value)
  {
    return value.ToString();
  }
}

Такой код не будет работать, потому что static методы не наследуются, да и для такого не предназначены.

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

interface ITypeFactory<T> where T : IType
{
  T Parse(string input);
}
class TypeFactory : ITypeFactory<Type> where T : IType
{
  public virtual Type Parse(string input) { ... }
}
class SecondTypeFactory : TypeFactory
{
  public override Type Parse(string input) { ... }
}
class ThirdTypeFactory : ITypeFactory<ThirdType>
{
  public ThirdType Parse(string input) { ... }
}

Соответственно в нашем классе TypeProcessor произойдут изменения:

class TypeProcessor<T> where T : IType
{
  private readonly ITypeFactory<T> factory;
  TypeProcessor(ITypeFactory<T> factory)
  {
    this.factory = factory;
  }
  public void Process(string input)
  {
    var someObject = this.factory.Parse(input);
    Console.WriteLine(this.ProcessInternal(someObject));
  }
  protected string virtual ProcessInternal(T value)
  {
    return value.ToString();
  }
}

Собственно, об этом и говорит паттерн Фабричный метод (можно посмотреть картинку на wiki). Есть Creator для общего типа и ConcreteCreator, который создает объекты конкретного типа.

В дополнение приведу статью, где автор рассуждает на тему использования статики в C#.

READ ALSO
Делегаты и события

Делегаты и события

Создать класс Банк, с использование события ввода пин-кода(если неверный, повторить попытку) снятие и пополнение на счетКласс создал, но с пин-кодом...

297
Task завершается через 15 минут работы

Task завершается через 15 минут работы

Написал программу которая должна раз в секунду проверять ping до двух серверовПроблема в том, что примерно через 15 минут таски перестают выполняться

157