C # «статический абстрактный» метод альтернатива создания дочернего класса - PullRequest
0 голосов
/ 07 мая 2018

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

Итак, представьте такую ​​структуру кода:

abstract class Element
class A : Element
class B : Element
class C : Element

Родительский класс Element обрабатывает загрузку файлов и сохраняет дочерние классы в структуру данных, такую ​​как XML-файл.

Чтобы сохранить все элементы, класс Element создает базовую структуру XML и передает XmlElement в метод OnSave () каждого дочернего класса. У каждого дочернего элемента есть немного отличающаяся структура данных, поэтому они реализуют, как сохранить себя в XmlElement, который родитель передал им.

Однако для загрузки родительский класс должен выполнить итерацию по заданному XML-файлу и создать экземпляры дочерних объектов на основе информации, содержащейся в файле. Поскольку система сохранения сконфигурирована для хранения всех дочерних экземпляров в ветви для соответствующего типа, она знает, какой тип создавать для каждого набора данных. Поскольку файловые структуры всех дочерних объектов снова немного отличаются, было бы разумно, чтобы дочерние объекты реализовали статическую функцию, которая создает собственный экземпляр, заполненный данными, передаваемыми указанной функции родительским объектом. Поскольку мне нужно, чтобы все дочерние элементы реализовывали эту функцию, я инстинктивно начал печатать

protected static abstract Element Load(XmlElement xml);

Пока я не заметил, что это не имеет смысла.

Теперь у меня вопрос: как интеллектуальная система, подобная этой, будет реализована?

Edit: Обратите внимание, что функция Load элемента будет статической.

1 Ответ

0 голосов
/ 07 мая 2018

Вы можете использовать Заводской метод / Шаблон

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

Основная идея состоит в том, чтобы переместить ваше создание (создание логики ваших производных классов) в отдельный класс / метод.

Когда вы вводите новый производный класс, вам нужно только реализовать новый производный класс и обновить метод фабрики.

Расширение на вашем примере:

public abstract class Element
{
    public abstract void Load(XmlElement xml);
}

public sealed class ClassA
    : Element
{
    public override void Load(
        XmlElement xml)
    {
        throw new NotImplementedException();
    }
}

public sealed class ClassB
    : Element
{

    public override void Load(
        XmlElement xml)
    {
        throw new NotImplementedException();
    }
}

public sealed class ClassC
    : Element
{
    public override void Load(
        XmlElement xml)
    {
        throw new NotImplementedException();
    }
}

Factory:

public static class ElementFactory
{
    public static Element Create(
        XmlElement element)
    {            
        if (element.Value == "1")
        {
            return new ClassA();
        }
        else if (element.Value == "2")
        {
            return new ClassB();
        }
        else if (element.Value == "3")
        {
            return new ClassB();
        }

        throw new Exception("Could not determine element class");
    }
}

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

XmlDocument xmlDoc = new XmlDocument();
var xmlElement = xmlDoc.CreateElement("element1");

var element = ElementFactory.Create(xmlElement);

element.Load(xmlElement);

Вы также можете удалить метод load и использовать конструктор каждого производного класса:

public abstract class Element
{
    public Element(
        XmlElement xml)
    {
    }
}

public sealed class ClassA
    : Element
{
    public ClassA(XmlElement xml) : base(xml)
    {
    }
}

public sealed class ClassB
    : Element
{
    public ClassB(XmlElement xml) : base(xml)
    {
    }
}

public sealed class ClassC
    : Element
{
    public ClassC(XmlElement xml) : base(xml)
    {
    }
}

Обновлен завод:

Тогда ваш код вызова становится проще:

public static Element Create(
    XmlElement element)
{            
    if (element.Value == "1")
    {
        return new ClassA(element);
    }
    else if (element.Value == "2")
    {
        return new ClassB(element);
    }
    else if (element.Value == "3")
    {
        return new ClassB(element);
    }

    throw new Exception("Could not determine element class");
}

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

XmlDocument xmlDoc = new XmlDocument();
var xmlElement = xmlDoc.CreateElement("element1");

var element = ElementFactory.Create(xmlElement);
...