简体   繁体   English

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

[英]Object-oriented design pattern to avoid if/then/else statements

Because I'm relative new to OOP / C# i don't know the right pattern to solve this: 因为我对OOP / C#相对较新,我不知道解决这个问题的正确模式:

I have to build a plugin architecture for different IO Providers. 我必须为不同的IO提供商构建一个插件架构。 The host reads the needed Provider name / type from the config, then it should the provider instantiate and parameterize. 主机从配置中读取所需的提供程序名称/类型,然后它应该是提供程序实例化和参数化。

So I have basically this interfaces: 所以我基本上有这个接口:

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; }
}

As you see the derived, specialized IO Providers have different additional parameter properties which the base interface doesn't have. 如您所见,派生的专用IO提供程序具有基本接口所没有的不同附加参数属性。 To avoid if/then/else or switch statements my idea was to use a factory pattern. 为了避免if / then / else或switch语句我的想法是使用工厂模式。

But if i understand this correctly it doesn't solve my if/then/else problem because on the client I have to check the derived type to supply the correct parameters. 但如果我理解正确,它不能解决我的if / then / else问题,因为在客户端我必须检查派生类型以提供正确的参数。

So the program flow on the Host would be something like this: Host reads config, gets Name/Type of needed Provider Host calls Factory and gets the Provider 因此,主机上的程序流将是这样的:主机读取配置,获取所需的名称/类型提供者主机调用工厂并获取提供者

But how avoid this - is there a pattern to solve this without if/then/else? 但是如何避免这种情况 - 有没有if / then / else解决这个问题的模式?

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

You can replace switch statement with polymorphism. 您可以使用多态替换switch语句。 Just allow each provider to configure itself from config. 只允许每个提供程序从config配置自己。 This is a best option, because each provider knows which values to look for: 这是一个最佳选择,因为每个提供程序都知道要查找的值:

provider.Configure();

This method should exist in base interface: 此方法应存在于基接口中:

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

And each provider implement it: 每个提供商都实现它:

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

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

Main benefit of this approach is that you will have only one place to change, when new provider added to your application - just add new provider class, which knows how to configure itself. 这种方法的主要好处是,只有一个地方可以更改,当新的提供程序添加到您的应用程序时 - 只需添加新的提供程序类,它知道如何自行配置。 You don't need to change host implementation also. 您也不需要更改主机实现。 And your host will satisfy OCP principle - open for extension (you can add new providers), but closed for modification (you don't need to modify existing code when new provider added). 并且您的主机将满足OCP原则 - 打开扩展(您可以添加新的提供程序),但关闭以进行修改(您不需要在添加新提供程序时修改现有代码)。

Also you can pass some configuration object to Configure(IConfiguration config) to this method (it will make your code testable, and not dependent on static ConfigurationManager ). 您还可以将一些配置对象传递给Configure(IConfiguration config)到此方法(它将使您的代码可测试,而不依赖于静态ConfigurationManager )。

If you're dead set on getting rid of the if/else statements, than you can maybe have a loader in your base class, which you pass all the parameters into, and then have each class overload it, and only use the parameters they needs. 如果您已经完成了删除if / else语句,那么您可能在基类中有一个加载器,您将所有参数传递给它,然后让每个类重载它,并且只使用它们的参数需要。

I will way that that is a desirable patter only if all your derived classes are guaranteed to use the same small collection of parameters, just in different ways. 只有当所有派生类都保证使用相同的小参数集合时,我才会认为这是一个理想的模式,只是以不同的方式。 Otherwise, the if / else statements are probably desirable 否则,可能需要if / else语句

In the end you always end up having to use a conditional statement. 最后,您总是必须使用条件语句。

Sure, you may use some library to abstract this. 当然,您可以使用一些库来抽象它。 Such as a Dependency Injection libary and based in some constructors you may be able to do this without ifs. 例如依赖注入库和基于某些构造函数,您可以在没有ifs的情况下执行此操作。

But... 但...

Its really not worth it, you'll add a lot of complexity to your code just to make it more elegant and the tradeoff it usually not worth it. 它真的不值得,你会为你的代码增加很多复杂性,只是为了让它更优雅,并且通常不值得这样做。

Thats not to say you can't do something better. 多数民众赞成不是说你不能做得更好。 Shooting from the hip, i'd add a method like this to the interface. 从臀部拍摄,我会在界面上添加这样的方法。

void Init(Dictionary parameters), and in each implementation you read from the dictionary and initialize the needed properties void Init(字典参数),在每个实现中,您从字典中读取并初始化所需的属性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM