作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个将 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/
我是一名优秀的程序员,十分优秀!