Устранение лишних условий

Я хочу реорганизовать следующий код, чтобы избежать if... else, так что мне не нужно менять метод каждый раз, когда приходит новый тип опроса (принцип Open/closed). Ниже приведен фрагмент кода, который я рассматриваю для реорганизации:

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?

Ответ 1

Если param2 и param3 являются конкретными требованиями AnonymousSurvey, они не должны быть частью интерфейса, а конкретного класса:

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

Ответ 2

почему бы не добавить перегрузку

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

Ответ 3

Это поможет узнать, какие типы параметров. Если они все одинаковые, то вы можете в С# по крайней мере использовать ключевое слово params и отправить столько параметров, сколько необходимо. Если нет, то вам может понадобиться передать словарь параметров, а затем оставьте его до класса реализации, чтобы применить объект к правильному типу.

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

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

Возможно, лучшим способом было бы включить параметры в вызов метода factory и установить factory значения для правильного типа при его создании, тогда вы можете вызвать метод без каких-либо параметров.

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

и

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

Ответ 4

Кажется, это случай 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));
    }
}

Ответ 5

Ваш опубликованный код не или . Независимо от того, похоже, вы хотите тип параметра.

Ответ 6

У вас может быть еще один абстрактный класс, расширяющий BaseSurvey, который расширяется InvitationalSurvey и ReturnLaterSurvey. Этот абстрактный класс мог реализовать DoSomething(param1,param2,param3), вызывая его собственный абстрактный метод DoSomething(param1), который InvitationalSurvey и ReturnLaterSurvey мог бы расширять int 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();
    }
}