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