我有不同的组件,可以提供导出数据。之后数据将被写入
.xml
,.csv
,.xls
或.docx
文件。
对于每种类型,我都有像
这样的编写器组件 XmlWriter
,CsvWriter
等。
目前我有一个if ... else
结构来决定我想要使用哪个Writer object
。
是否存在替换此if ... else
结构的设计模式?
答案 0 :(得分:2)
控制反转(IoC)与依赖注入(DI)相结合将非常适合这种情况。首先,IoC允许在编译时避免具体的对象耦合,同时仍然知道“一些”实现细节,因此,彼此之间没有直接的依赖关系。现在,WikiPedia引用的依赖注入...
依赖注入是一种软件设计模式,允许删除硬编码的依赖项,并且可以在运行时或编译时更改它们
它允许您在非常强大的依赖项之间切换,因为您实际上可以更改对象的实现,而无需重新编译整个项目并使用模式的其他变体(例如工厂模式)重新部署它或Service Locator Pattern,因为您可以在运行时或编译时“注入”依赖项。
现在,您将如何使用您的案例场景实现这一目标?至少,您需要一个具体的对象来完成所有这些工作并隐藏实现细节....
public class DataExportManager
{
private IDataExporter _exporter;
public DataExportManager(IDataExporter exporter)
{
this._exporter = exporter;
}
public void ExportData()
{
this._exporter.Export();
}
}
请注意,此类使用接口IDataExporter
来导出数据,但它不了解实现该接口的底层具体对象,它只是允许使用者代码“注入”实现细节。不用说,它不是在构造函数中使用接口,而是可以接受基类或抽象类。然后,您需要实现具体对象和接口。界面看起来像这样......
public interface IDataExporter
{
void Export();
}
和这样的实现......
public WordDataExporter : IDataExporter
{
public void Export(){//export to Word logic}
}
public PdfDataExporter : IDataExporter
{
public void Export(){//export to pdf logic}
}
public ExcelDataExporter : IDataExporter
{
public void Export(){//export to excel logic}
}
等等。然后你知道你有一个对象DataExportManager
可以注入实现IDataExporter
接口的对象。这就是依赖注入的实际应用。但是,你如何注射它?这就是IoC派上用场的时候。您可以实现工厂对象或服务定位器,以将此DataExporters注入DataExportManager。简化版本将是一个简单的对象,用于确定在编译时要注入的对象...
public class ExporterFactory
{
public static IDataExporter GetCurrentExporter()
{
return new WordDataExporter();
}
}
然后你会像这样注入WordDataExporter
......
DataExportManager manager = new DataExportManager(ExportFactory.GetCurrentExporter());
这样做的好处是,您可以更改实现IDataExporter
界面的对象,甚至不会注意到它DataExportmanager
将开始导出为PDF,Excel或您喜欢的任何内容。它非常简单,可以删除应用程序层中的依赖项。当然,你可以让它更漂亮,更聪明。
如果您使ExportFactory
读取配置文件以确定应该提供哪个IDataExporter
,您甚至可以在不重新编译应用程序的情况下执行此操作。
这个非常好且受欢迎的社区项目名为Windsor Castle,可以很好地完成这项工作,甚至可以让您管理这些依赖项和服务定位器的生命周期。
现在,回答你的问题。没有设计模式可以取代if...else
或switch...case
希望有所帮助
答案 1 :(得分:1)
不是真正的设计模式,但您可以使用每个组件并添加一个名为Write
的方法的接口,然后在每个组件类中,您可以实现该接口并使用适当的编写器对象。这样而不是if ... else
您只有一个命令:IComponentWriter.Write(params)
如果要使用依赖注入(取决于您编写的语言),可以向每个组件类添加IWriter
属性,然后在服务定位器中,您可以使用特定实现映射每个类IWriter
接口,但这与巨型if .. else
几乎相同,你刚刚把问题转移到了IoC类。
我会在开头使用界面设计。