Как избежать условий

Я хочу реорганизовать следующий код, чтобы избежать 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?

6 ответов

Если 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
    }
}

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

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

Это помогло бы узнать, какие типы параметров. Если они все одинаковы, то вы можете, по крайней мере, в 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();

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

Ваш опубликованный код не является C# или Java. В любом случае, это звучит так, как будто вам нужен тип Option.

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