C# 避免其他情况
我想重构以下代码以避免if…else,这样我就不必在每次出现新的调查类型时都更改方法(开放/封闭原则)。下面是我正在考虑重构的一段代码:C# 避免其他情况,c#,oop,solid-principles,open-closed-principle,java,C#,Oop,Solid Principles,Open Closed Principle,Java,我想重构以下代码以避免if…else,这样我就不必在每次出现新的调查类型时都更改方法(开放/封闭原则)。下面是我正在考虑重构的一段代码: if (surveyType == SurveySubType.Anonymous) { DoSomething(param1, param2, param3); } else if (surveyType == SurveySubType.Invitational) { DoSomething(param1); } else if (sur
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传递给InvitationSurvey和ReturnLaterSurvey类有什么好处?您发布的代码不是或。无论如何,听起来你想要一个。你可以有另一个抽象类扩展
BaseSurvey
,它InvitationalSurvey
和ReturnLaterSurvey
都扩展了。这个抽象类可以通过调用自己的抽象方法DoSomething(param1,param2,param3)
来实现DoSomething(param1)
,这InvitationalSurvey
和returnlatersvey
可以扩展DoSomething(param1,param2,param3)
为什么不添加一个重载呢
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);
}
及
这似乎是
过载的情况
,但已经有人建议了。作为一种替代方法,为什么不这样做呢,这意味着为参数指定一个默认值使其成为可选的。看看下面的例子
我演示了一个整数类型,您可以更改该类型并使您的默认值最适合
如果
param2
和param3
是匿名调查
的具体要求,则它们不应是接口的一部分,而是具体类别的一部分:
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
}
}
我能想到的最好办法就是为参数添加一个类似的类结构。。。换句话说,创建一个类似BaseSurveyArguments的基类,并根据需要对其进行扩展。不过不是很优雅。看看这个,我很高兴Delphi有了
case
开关。在C#中没有这样的替代方法吗?C#
确实有case
语句,在中也提到了该语句。也许有一些聪明的方法可以使用委托或实体引用使其更加流畅,尽管我自己还没有体验过。我也认为switch
和默认参数一起使用是一种解决方案。在Python中,可以为所有参数指定默认值,并提供更新参数的列表。另一个问题是,如果只有一种DoSomething
方法。为什么不ProcessLateSurvey
,ProcessAnonSurvey
etc.方法?这个问题似乎离题了,因为它是关于。你的个人资料图片背后隐藏着什么样的宣传?我认为@nurettin暗示你可能是在通过你的avatar@DavidWallace如果你想直接向网站上的人提问,您可以使用@符号,以便他们获得警报。假设这是针对我的,我显然是在暗示你在使用一张宣传画,并询问它的含义。@nurettin我认为你非常清楚它的含义,你只是想挑起一场战斗。我不认为Stack Overflow是合适的论坛,是吗?@DavidWallace我同意,Stack Overflow不是你宣传的地方。我们有reddit。DoSomething不应该被提取为接口,然后你可以使用依赖注入吗?你可以这样做。这是我首选的设计方法,但正如前面所述,BaseSurvey
是一种纯粹的抽象类型,因此从客户的角度来看,它在组成上相当于一个接口。@MarkSeemann您能给我一个客户如何调用DoSomething的示例吗?需要对匿名调查进行类型检查以通过param2和param3权限?何时创建邀请调查
,返回后调查
,匿名调查
对象?谁拥有param2
和param3
值?@MarkSeemann正如我上面所示,工厂方法创建对象。param2和param3仅与AnonymousSurvey类相关。然后,您需要再次引入if…else类型检查来确定要调用哪个工厂方法。@fahmi-没有办法解决这个问题。但它确实在创作代码中进行了本地化。
var survey = surveyFactory.CreateAnonymousSurvey(param1, param2, param3);
survey.DoSomething();
var survey = surveyFactory.CreateReturnLaterSurvey(param1);
survey.DoSomething();
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));
}
}
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
}
}