C# 'static abstract' 方法替代实例化 child class
C# 'static abstract' method alternative to instantiate child class
我知道我的要求不会以这种方式起作用,但我认为我最初的想法并不那么愚蠢。
所以,想象一下这样的代码结构:
abstract class Element
class A : Element
class B : Element
class C : Element
元素 parent class 正在处理文件加载并将 child classes 保存到数据结构,如 XML 文件。
为了保存所有元素,元素 class 创建基本 XML 结构并将 XmlElement 传递给每个 child class 的 'OnSave()' 方法。
每个 child 的数据结构略有不同,因此他们正在实施如何将自己保存在 parent 传递给他们的 XmlElement 下。
然而,要加载,parent class 应该遍历给定的 XML 文件并根据其中包含的信息实例化 child objects的文件。
因为保存系统配置为将所有 child 个实例存储在相应类型的分支下,所以它知道为每个数据集实例化哪种类型。
因为所有 child objects 的文件结构再次略有不同,所以让 child 实现一个静态函数来创建一个自身的实例并填充传递给的数据的实例是明智的由parent表示的函数。
因为我需要所有 child 来实现这个功能,所以我本能地开始输入
protected static abstract Element Load(XmlElement xml);
直到我发现这没有意义。
我现在的问题是:如何以智能方式实施这样的系统?
编辑:
请注意,Element 的 Load 函数将是静态的。
您可以使用 Factory Method/Pattern
In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.
基本思想是将您的创建(实例化您派生的 classes 的逻辑)移动到单独的 class/method。
当你引入一个新的派生class你只需要实现你的新派生class并更新你的工厂方法。
扩展您的示例:
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方法,使用每个派生的构造函数class:
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);
我知道我的要求不会以这种方式起作用,但我认为我最初的想法并不那么愚蠢。
所以,想象一下这样的代码结构:
abstract class Element
class A : Element
class B : Element
class C : Element
元素 parent class 正在处理文件加载并将 child classes 保存到数据结构,如 XML 文件。
为了保存所有元素,元素 class 创建基本 XML 结构并将 XmlElement 传递给每个 child class 的 'OnSave()' 方法。 每个 child 的数据结构略有不同,因此他们正在实施如何将自己保存在 parent 传递给他们的 XmlElement 下。
然而,要加载,parent class 应该遍历给定的 XML 文件并根据其中包含的信息实例化 child objects的文件。 因为保存系统配置为将所有 child 个实例存储在相应类型的分支下,所以它知道为每个数据集实例化哪种类型。 因为所有 child objects 的文件结构再次略有不同,所以让 child 实现一个静态函数来创建一个自身的实例并填充传递给的数据的实例是明智的由parent表示的函数。 因为我需要所有 child 来实现这个功能,所以我本能地开始输入
protected static abstract Element Load(XmlElement xml);
直到我发现这没有意义。
我现在的问题是:如何以智能方式实施这样的系统?
编辑: 请注意,Element 的 Load 函数将是静态的。
您可以使用 Factory Method/Pattern
In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.
基本思想是将您的创建(实例化您派生的 classes 的逻辑)移动到单独的 class/method。
当你引入一个新的派生class你只需要实现你的新派生class并更新你的工厂方法。
扩展您的示例:
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方法,使用每个派生的构造函数class:
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);