我正在开发一个库来转换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语句。当我创建一个新的子类时,我仍然需要向字典中添加元素。
有没有更好的方法呢?敬请指教。
发布于 2015-02-27 08:09:03
我想说你的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!!
正如您所看到的,这可能会由于几个原因导致运行时失败。找不到类型,找到类型但没有公共无参数构造函数,找到类型但不是从DocxElement
派生,等等。
所以最好还是坚持使用Dictionary
选项IMO。
https://stackoverflow.com/questions/28760062
复制相似问题