C#'static abstract'方法替代实例化子类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#'static abstract'方法替代实例化子类相关的知识,希望对你有一定的参考价值。

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

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

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

Element父类正在处理文件加载并将子类保存到XML文件之类的数据结构。

为了保存所有Elements,Element类创建基本的XML结构,并将XmlElement传递给每个子类的'OnSave()'方法。每个子节点的数据结构略有不同,因此它们实现了如何在父节点传递它们的XmlElement下保存自己。

但是,要加载,父类应遍历给定的XML文件,并根据文件中包含的信息实例化子对象。由于保存系统配置为在相应类型的分支下存储所有子实​​例,因此它知道要为每个数据集实例化哪种类型。因为所有子对象的文件结构再次略有不同,所以让子实现一个静态函数是明智的,该函数创建一个自己的实例,其中填充了父代传递给所述函数的数据。因为我要求所有孩子都实现这个功能,我本能地开始打字

protected static abstract Element Load(XmlElement xml);

直到我注意到这没有意义。

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

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

答案

你可以使用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);

以上是关于C#'static abstract'方法替代实例化子类的主要内容,如果未能解决你的问题,请参考以下文章

关于Abstract,static,final的理解

abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?

static & abstract

部分关键字--this/extends/super/static/final/abstract/访问权限总结

abstract和interface的区别?

abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?