反竞选活动

And*_*mer 29 design-patterns

我最近遇到了一个非常有趣的网站,表达了一个非常有趣的想法 - 反竞选活动.您可以在www.antiifcampaign.com上看到这一点.我必须同意复杂的嵌套IF语句是后方的绝对痛苦.我目前正在进行一个项目,直到最近才有一些疯狂的嵌套IF向右滚动相当多的方式.我们以两种方式解决了问题 - 我们使用Windows Workflow Foundation来解决路由(或工作流程)问题.我们正在利用ILOG Rules for .NET(最近由IBM购买!!)实施所有业务规则.这在很大程度上已经治愈了我们的嵌套IF痛苦...但我发现自己想知道有多少人以AntiIfCampaign的优秀人士建议的方式(通过这里看到一个例子)通过创建大量抽象类来解决他们的痛苦表示最初由嵌套IF覆盖的给定方案.我想知道解决这种复杂性的另一种方法是否也可能是使用诸如StructureMap之类的IoC容器来移入和移出不同的功能.无论哪种方式...

问题: 给定一个场景,我有一个嵌套的复杂IF或SWITCH语句,用于评估给定类型的事物(比如评估一个枚举),以确定我想如何通过枚举类型处理该事物的处理 - 有什么一些如何在不使用IF或SWITCH分层结构的情况下进行相同形式的处理?

public enum WidgetTypes
{
    Type1,
    Type2,
    Type3,
    Type4
}

...

WidgetTypes _myType = WidgetTypes.Type1;

...

switch(_myType)
{
    case WidgetTypes.Type1:
        //do something
        break;

    case WidgetTypes.Type2:
        //do something
        break;

    //etc...
}
Run Code Online (Sandbox Code Playgroud)

Ed *_* S. 59

问题不在于'if'语句,而是编写错误代码的程序员.

编辑:另外,正如其他人所指出的,当你使用if语句来检查对象的类型时,你应该使用多态(如果可用),但是if语句本身是非常有用和基本结构.

  • 任何人都可以向编写错误代码的程序员提出好的代码吗? (4认同)

小智 35

在Java中,很容易将枚举用作多态反if代理.

public class AntiIf {
  public enum WidgetTypes {
    Type1 {
      public void doSomething() {
        //...
      }},
    Type2 {
      public void doSomething() {
        //...
      }},
    Type3 {
      public void doSomething() {
        //...
      }},
    Type4 {
      public void doSomething() {
        //...
      }};

    public abstract void doSomething();
  }

  WidgetTypes _myType; // set by someone to one of the types.

  public void someFunction() {
    //...
    _myType.doSomething();
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 从Java 8开始,这可能会更具表现力..然后再一个简单的`Map <WidgetType,Runnable>`也会做同样的事情...... (2认同)

Dar*_*ryl 23

反对如果是愚蠢的.

有时替换条件via多态是正确的做法,但在那些情况下,if语句不是真正的问题.真正的问题是以非抽象方式处理抽象类型,即未能在基类的抽象层次上进行思考.

其他时候可以替换条件via多态,但这样做是个坏主意.导致您将一种类型与另一种类型区别对待的逻辑可能属于算法本身,而不属于单个类.将该逻辑移动到类可能会导致类的代码过度地意识到使用它们的上下文.

但大多数情况下,if语句与多态无关.摆脱if语句是错误的目标.

反对如果是愚蠢的.

  • 正是这样.不幸的是,我的幽默感必须被打破,因为我无法分辨https://cirillocompany.de/pages/anti-if-campaign是否严重或只是具有讽刺意味. (2认同)

Wil*_*iam 16

用多态替换条件

  • 这仅适用于您的条件基于参数的TYPE ...这可能正是您打算传达的内容.:) (3认同)

Mar*_*age 14

切换语句通常可以用多态替换:

abstract class WidgetBase {
  public abstract void DoSomething();
}

class Widget1 : WidgetBase {
  public override void DoSomething() {
    // Do something ...
  }
}

class Widget2 : WidgetBase {
  public override void DoSomething() {
    // Do something ...
  }
}

...

Widget widget = new Widget1(); // Use a factory pattern instead.
widget.DoSomething();
Run Code Online (Sandbox Code Playgroud)

  • 我在这里的问题是如何在不评估我需要处理的小部件类型的情况下如何知道我要使用哪个小部件?我可以看到使用接口和WidgetFactory来返回相应的小部件......但是在WidgetFactory(或某个地方)内部我不会有一些评估类型代码来帮助我决定返回/使用哪个小部件? (2认同)

IRB*_*BMe 12

您可以使用命令模式根据某些值或输入执行命令.

在回答你的问题时,你可以使用一个简单的查找表或多态来实现这一点,虽然它将逻辑放在程序的不同部分,这可能确实是正确的事情.以下是C#中的几个示例:

var commands = new Dictionary<WidgetTypes, Action>()
    {
        { WidgetTypes.Type1, () => Console.WriteLine("Type 1") },
        { WidgetTypes.Type2, () => Console.WriteLine("Type 2") },
        { WidgetTypes.Type3, () => Console.WriteLine("Type 3") },
        { WidgetTypes.Type4, () => Console.WriteLine("Type 4") }
    };

commands[WidgetTypes.Type1]();
Run Code Online (Sandbox Code Playgroud)
public interface ICommandHandler
{
    void HandleCommand();
}

public class Command1Handler : ICommandHandler
{
    public void HandleCommand()
    {
        Console.WriteLine("Type 1");
    }
}

// ...

var commands = new Dictionary<WidgetTypes, ICommandHandler>()
    {
        { WidgetTypes.Type1, new Command1Handler() },
        { WidgetTypes.Type2, new Command2Handler() },
        { WidgetTypes.Type3, new Command3Handler() },
        { WidgetTypes.Type4, new Command4Handler() }
    };

commands[WidgetTypes.Type1].HandleCommand();
Run Code Online (Sandbox Code Playgroud)

以及一个奖励反射方法,用于调用具有相同名称的当前对象上的方法:

public void Type1()
{
    Console.WriteLine("Type 1");
}

//...

var type = WidgetTypes.Type2;
typeof(MyClass).GetMethod(type.ToString()).Invoke(this, new object[] { });
Run Code Online (Sandbox Code Playgroud)

注意:实际上并不这样做


Kaw*_*awa 6

...什么?

没有某种比较,我无法想象如何做这样的事情.完全没有.

我可以想象一个反goto运动,但如果看起来像一个非常该死的控制流程结构给我.

  • 好的,所以有替补.坦率地说,我发现这些替代品比原始代码更难以理解. (3认同)

Chr*_*sma 6

不要担心简单的if语句或直接的switch语句.

担心这个:

  1. 可怕的嵌套if语句(箭头反模式).这些东西无法读取和调试.
  2. if(或case)带有bagilion代码行."好吧,我们这样做了......在这种情况下,那个......那个......在这种情况下.也很难读.几乎不可能测试或调试.
  3. 超级复杂的条件:如果(碗和KitchenSink或BathroomTub AND ...).你还在测试什么?在方法中包装 - 在这种情况下:CanHoldWater().

  • 通常,"if()语句别if()语句别if()语句"构造,一般化开关的排序,易于阅读和理解(假设各个语句不太长).你已经解决了问题. (2认同)