我知道我所问的并不是以这种方式工作,但我认为我最初的想法不是那么愚蠢。
所以,想象一下像这样的代码结构:
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函数是静态的。
答案 0 :(得分:2)
在基于类的编程中,工厂方法模式是一种创建模式,它使用工厂方法来处理创建对象的问题,而无需指定将要创建的对象的确切类。这是通过调用工厂方法创建对象来完成的 - 在接口中指定并由子类实现,或者在基类中实现并可选地由派生类覆盖 - 而不是通过调用构造函数。
基本思想是将您的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);