选择Designpattern或Dependency注入

时间:2014-01-09 15:40:49

标签: design-patterns

我有不同的组件,可以提供导出数据。之后数据将被写入 .xml.csv.xls.docx文件。

对于每种类型,我都有像

这样的编写器组件

XmlWriterCsvWriter等。

目前我有一个if ... else结构来决定我想要使用哪个Writer object

是否存在替换此if ... else结构的设计模式?

2 个答案:

答案 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...elseswitch...case

希望有所帮助

答案 1 :(得分:1)

不是真正的设计模式,但您可以使用每个组件并添加一个名为Write的方法的接口,然后在每个组件类中,您可以实现该接口并使用适当的编写器对象。这样而不是if ... else您只有一个命令:IComponentWriter.Write(params)

如果要使用依赖注入(取决于您编写的语言),可以向每个组件类添加IWriter属性,然后在服务定位器中,您可以使用特定实现映射每个类IWriter接口,但这与巨型if .. else几乎相同,你刚刚把问题转移到了IoC类。

我会在开头使用界面设计。