gpt4 book ai didi

c# - 创建对象族取决于字符串或枚举违反开闭原则

转载 作者:行者123 更新时间:2023-11-30 17:44:58 25 4
gpt4 key购买 nike

我正在开发一个将 HTML 文档转换为 word 文档的库。这是通过遍历 HTML 文档并逐个处理 HTML 元素来完成的。有一系列类来处理每个 HTML 标记。

public abstract class DocxElement
{
public void Process();
}

public class DocxTable : DocxElement
{
public override void Process(){}
}

public class DocxDiv : DocxElement
{
public override void Process(){}
}

上面的类负责处理对应的 html。因此,每当我扩展库以支持额外的 html 标记时,我将只从 DocxElement 创建一个子类。 html 解析器在遇到 HTML 标记时使用工厂类生成集中的 DocxElement 类。

public class ElementFactory
{

public DocxElement Resolve(string htmlTag)
{
switch(htmlTag)
{
case "table":
return new DocxTable();

case "div":
return new DocxDiv();
}
}
}

现在感觉违反了开闭原则。我不想仅仅因为设计模式需要而使用反射。所以我创建了一个单例字典来注册元素类。

Dictionary<string, Func<DocxElement>> doc;

doc.Add("table",()=>{ new DocxTable();});

最后我能够消除 switch 语句。当我创建一个新的子类时,我仍然需要向字典中添加元素。

有没有更好的方法来做到这一点?请指教。

最佳答案

我会说您的 Dictionary 方法很好。任何其他试图使这个泛型的东西都会失去静态编译时检查。如果您准备好牺牲编译时检查,则可以使用反射使此代码通用。

public class ElementFactory
{
public DocxElement Resolve(string htmlTag)
{
var type = Type.GetType(string.Format("{0}.Docx{1}",
typeof(ElementFactory).Namespace,
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(htmlTag)));
return (DocxElement)Activator.CreateInstance(type);
}
}

使用方法:

ElementFactory factory = new ElementFactory();
var table = factory.Resolve("table");//Works
var div = factory.Resolve("div");//Works
var span = factory.Resolve("span");//Explodes!!

如您所见,由于多种原因,这可能会导致运行时失败。找不到类型,找到类型但没有公共(public)无参数构造函数,找到类型但它不是从 DocxElement 派生的,等等。

所以你最好坚持使用 Dictionary 选项 IMO。

关于c# - 创建对象族取决于字符串或枚举违反开闭原则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28760062/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com