避免如果其他条件

时间:2014-03-27 04:51:17

标签: c# oop solid-principles open-closed-principle

我想重构以下代码以避免if ... else以便每次新调查类型进入时我都不必更改方法(开放/封闭原则)。以下是我正在考虑重构的代码:

if (surveyType == SurveySubType.Anonymous)
{
    DoSomething(param1, param2, param3);

}
else if (surveyType == SurveySubType.Invitational)
{
    DoSomething(param1);
}
else if (surveyType == SurveySubType.ReturnLater)
{    
    DoSomething(param1);
}

为了解决这个问题,我添加了以下类:

    public abstract class BaseSurvey
{
            public string BuildSurveyTitle()
            {
             ...doing something here
            }

    public abstract void DoSomething(int? param1,int?  param2,int?  param3);
}
public class InvitationalSurvey: BaseSurvey
{
    public override void DoSomething(int? param1,int?  param2,int?  param3)
    {
    //I don't need param2 and param3 here

    }
}


public class ReturnLaterSurvey: BaseSurvey
{
    public override void DoSomething(int? param1,int?  param2,int?  param3)
    {
    //I don't need param2 and param3 here

    }
}


public class AnonymousSurvey: BaseSurvey
{
    public override void DoSomething(int? param1,int?  param2,int?  param3)
    {

    //I need param2 and param3 here
    //do something
    }

}

这就是我的代码最终结果:

var survey = SurveyFactory.Create();
survey.DoSomething(param1,param2,param3);

我的问题是避免将param2和param3传递给InvitationalSurvey和ReturnLaterSurvey类会有什么好处?

6 个答案:

答案 0 :(得分:17)

如果param2param3AnonymousSurvey的具体要求,则它们不应该是界面的一部分,而应该是具体类的一部分:

public abstract class BaseSurvey
{
    public abstract void DoSomething(param1);
}

public class InvitationalSurvey: BaseSurvey
{
    public void DoSomething(param1)
    {
    }
}


public class ReturnLaterSurvey: BaseSurvey
{
    public void DoSomething(param1)
    {
    }
}


public class AnonymousSurvey: BaseSurvey
{
    private readonly object param2;
    private readonly object param3

    public AnonymousSurvey(param2, param3)
    {
        this.param2 = param2;
        this.param3 = param3;
    }

    public void DoSomething(param1)
    {
        // use this.param2 and this.param3 here
    }
}

答案 1 :(得分:3)

为什么不添加重载

doSometing(Param1){
 doSomething(Param1, null, null)
}

答案 2 :(得分:2)

了解参数类型是有帮助的。如果它们完全相同,那么您至少可以在C#中使用params关键字并根据需要发送尽可能多的参数。如果没有,那么您可能希望传递参数字典,然后将其留给实现类以将对象强制转换为正确的类型。

public abstract class BaseSurvey
{
    public abstract void DoSomething(params string[] parameters);
}

public abstract class BaseSurvey
{
    public abstract void DoSomething(Dictionary<string,object> parameters);
}

或许更好的方法是将参数合并到工厂方法调用中,并让工厂在创建时将值设置为正确的类型,然后您可以在没有任何参数的情况下调用该方法。

var survey = surveyFactory.CreateAnonymousSurvey(param1, param2, param3);
survey.DoSomething();

var survey = surveyFactory.CreateReturnLaterSurvey(param1);
survey.DoSomething();

答案 3 :(得分:2)

似乎是Overloading的情况,但已经提出过。因此,作为替代方案,为什么不这样做,这意味着为参数指定默认值 使其成为可选 。看看下面的例子。

我演示了一个整数类型,您可以更改类型并设置最适合的默认值。

Live Demo

using System;

public class Test
{
    public static void Main()
    {
        // your code goes here
        InvitationalSurvey iservey = new InvitationalSurvey();
        iservey.DoSomething(1, 1, 1);
        iservey.DoSomething(1);
    }
}

public abstract class BaseSurvey
{

}
public class InvitationalSurvey: BaseSurvey
{
    public void DoSomething(int param1, int param2 = 0, int param3 = 0)
    {
    //I don't need param2 and param3 here
    Console.WriteLine(string.Format("{0},{1},{2}",param1, param2, param3));
    }
}

答案 4 :(得分:1)

您发布的代码不是。无论如何,听起来你想要一个Option type

答案 5 :(得分:1)

您可以使用另一个扩展BaseSurvey的抽象类,其中InvitationalSurveyReturnLaterSurvey都会延伸。这个抽象类可以通过调用自己的抽象方法DoSomething(param1,param2,param3)来实现DoSomething(param1)InvitationalSurveyReturnLaterSurvey可以扩展DoSomething(param1,param2,param3)

的整数
public abstract class BaseSurvey
{
    public abstract void DoSomething(param1, param2, param3);
}

public abstract class SpecialSurvey : BaseSurvey
{
    public abstract void DoSomething(param1);

    public void DoSomething(param1, param2, param3)
    {
        DoSomething(param1);
    }
}

public class InvitationalSurvey: SpecialSurvey
{
    public void DoSomething(param1)
    {
         ReallyDoSomething();
    }
}