面向对象的设计模式避免if / then / else语句

时间:2012-11-27 16:16:07

标签: c# oop design-patterns

因为我对OOP / C#相对较新,所以我不知道解决这个问题的正确模式:

我必须为不同的IO提供商构建一个插件架构。 主机从配置中读取所需的提供程序名称/类型,然后它应该是提供程序实例化和参数化。

所以我基本上有这个接口:

public interface IoProvider //(Base interface, all Providers implements this)
{
    void Initialize();
    void Execute();
}

public interface IFileProvider: IoProvider
{
    string PropertyA { get; set; }
}

public interface ISmtpProvider : IoProvider
{
    string PropertyB { get; set; }
    string PropertyC { get; set; }
}

如您所见,派生的专用IO提供程序具有基本接口所没有的不同附加参数属性。 要避免if / then / else或switch语句我的想法是使用工厂模式。

但是,如果我理解正确,它不能解决我的if / then / else问题,因为在客户端我必须检查派生类型以提供正确的参数。

所以Host上的程序流程是这样的: 主机读取配置,获取所需提供商的名称/类型 主机调用Factory并获取提供程序

但是如何避免这种情况 - 如果没有if / then / else,是否有一种模式可以解决这个问题?

If (provider == typeOf(IFileProvider))  
PropertyA = value  
else if (provider == typeOf(ISmtpProvider))  
PropertyB = value  
PropertyC = value  
Elseif …

3 个答案:

答案 0 :(得分:14)

您可以使用多态替换switch语句。只允许每个提供程序从config配置自己。这是一个最佳选择,因为每个提供程序都知道要查找的值:

provider.Configure();

此方法应存在于基接口中:

public interface IoProvider 
{
    void Initialize();
    void Execute();
    void Configure();
}

每个提供商都实现它:

public interface ISmtpProvider : IoProvider
{
    string PropertyB { get; set; }
    string PropertyC { get; set; }

    public void Configure()
    {
        PropertyB = ConfigurationManager.AppSettins["B"];
        PropertyB = ConfigurationManager.AppSettins["C"];
    }
}

这种方法的主要好处是,只有一个地方可以更改,当新的提供程序添加到您的应用程序时 - 只需添加新的提供程序类,它知道如何配置自己。您也不需要更改主机实现。并且您的主机将满足OCP原则 - 打开扩展(您可以添加新的提供程序),但关闭以进行修改(您不需要在添加新提供程序时修改现有代码)。

此外,您可以将一些配置对象传递给Configure(IConfiguration config)此方法(它将使您的代码可测试,而不依赖于静态ConfigurationManager)。

答案 1 :(得分:0)

如果您已经完成了删除if / else语句,那么您可以在基类中加载一个加载器,将所有参数传递给它,然后让每个类重载它,并且只使用它他们需要的参数。

如果所有派生类都保证使用相同的小参数集,只是以不同的方式,我会认为这是一个理想的模式 。否则,if / else语句可能是可取的

答案 2 :(得分:-2)

最后,你总是不得不使用条件语句。

当然,您可以使用一些库来抽象它。比如依赖注入库和基于某些构造函数,你可以在没有ifs的情况下做到这一点。

但是...

它真的不值得,你会为你的代码增加很多复杂性,只是为了让它更优雅,并且通常不值得这样做。

这并不是说你不能做得更好。从臀部拍摄,我会在界面上添加这样的方法。

void Init(字典参数),在每个实现中,您从字典中读取并初始化所需的属性