C#'静态摘要'实例化子类的方法替代方法

时间:2018-05-07 08:46:04

标签: c# polymorphism abstract

我知道我所问的并不是以这种方式工作,但我认为我最初的想法不是那么愚蠢。

所以,想象一下像这样的代码结构:

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);

直到我注意到这没有用。

我现在的问题是:这样的系统如何以智能的方式实现?

编辑: 请注意,Element的Load函数是静态的。

1 个答案:

答案 0 :(得分:2)

您可以使用Factory Method/Pattern

  

在基于类的编程中,工厂方法模式是一种创建模式,它使用工厂方法来处理创建对象的问题,而无需指定将要创建的对象的确切类。这是通过调用工厂方法创建对象来完成的 - 在接口中指定并由子类实现,或者在基类中实现并可选地由派生类覆盖 - 而不是通过调用构造函数。

基本思想是将您的create(实例化派生类的逻辑)移动到单独的类/方法。

当您引入新的派生类时,您只需要实现新的派生类并更新工厂方法。

扩展您的示例:

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();
    }
}

厂:

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);