使用标记类来控制逻辑流程

时间:2009-05-07 14:54:18

标签: c# .net

我一直在查看一些代码,看到我的同事正在使用“标记类”来控制程序逻辑(参见下面的设计示例)。它似乎工作得很好,代码读起来非常好,但有一些东西闻起来......

namespace ConsoleApplication4983
{
    public class MyClass
    {
        static void Main()
        {
            var c = new MyClass();
            c.DoSomething(new Sequential());
            c.DoSomething(new Random());
        }

        public void DoSomething(ProcessingMethod method)
        {
            if (method is Sequential)
            {
                // do something sequential
            }
            else if (method is Random)
            {
                // do something random
            }
        }
    }

    public class ProcessingMethod {}
    public class Sequential : ProcessingMethod {}
    public class Random : ProcessingMethod {}
}

实现同样效果的更好方法是什么?枚举?属性?

7 个答案:

答案 0 :(得分:8)

标记 接口 是一种更好的做法,因为它们提供了更大的灵活性。

然而,在这种特定情况下,我认为虚拟调度是一种更好的解决方案。

using System;

namespace ConsoleApplication4983
{
    public class MyClass
    {
        static void Main()
        {
            var c = new MyClass();
            c.DoSomething(new Sequential());
            c.DoSomething(new Random());
        }

        public void DoSomething(ProcessingMethod method)
        {
            method.Foo();
        }
    }

    public class ProcessingMethod
    {
        public virtual void Foo() { }
    }
    public class Sequential : ProcessingMethod
    {
        public override void Foo() { }
    }
    public class Random : ProcessingMethod
    {
        public override void Foo() { }
    }
}

答案 1 :(得分:4)

您要做的是用strategy pattern替换它。策略定义了某些事情的完成方式 - 即算法。

public interface IProcessingMethod
{
    void Process();
}

public class SequentialProcess : IProcessingMethod
{
    public void Process( IProcessable obj )
    {
         do something sequentially with the obj
    }
}

public class ParallelProcess : IProcessingMethod
{
    public void Process( IProcessable obj )
    {
        do something in parallel with the obj
    }
}

public interface IProcessable
{
    void Process( IProcessingMethod method );
}

public class MyClass : IProcessable
{
     public void Process( IProcessingMethod method )
     {
         method.Process( this );
     }
}

...

var obj = new MyClass();
obj.Process( new SequentialProcess() );

现在,如果我有一个新类型的ProcessingMethod,我只需要为该方法创建一个类,并更改确定将哪个处理方法注入到我的IProcessable对象的Process方法的代码。

答案 2 :(得分:2)

我看到这个问题已经过时了,但我觉得所有答案都错过了这一点。

如果示例完全说明了所需功能的范围,那么此处使用的相应构造将是枚举类型。枚举类型是值类型;它们的功能与命名数值常量基本相同,具有出色的IDE自动完成支持。以下是修改为使用枚举类型的示例:

namespace ConsoleApplication4983
{
    public class MyClass
    {
        static void Main()
        {
            var c = new MyClass();
            c.DoSomething(ProcessingMethod.Sequential);
            c.DoSomething(ProcessingMethod.Random);
        }

        public void DoSomething(ProcessingMethod method)
        {
            if (method == ProcessingMethod.Sequential)
            {
                // do something sequential
            }
            else if (method == ProcessingMethod.Random)
            {
                // do something random
            }
        }
    }

    public enum ProcessingMethod
    {
        Sequential,
        Random
    }
}

其他答案正在参考更精细的模式。我认为他们在“标记类”这个术语中读了太多。有时策略模式,虚拟调度等是一种很好的方法,但在这种情况下,我认为Enum是对这段代码最简单的改进。

答案 3 :(得分:1)

他几乎在那里,但并不完全,这可能就是你所看到的。关于该类型的if语句是难闻的气味。应该在ProcessingMethod基类上执行某些操作,并且扩展它的每个类型都应该有自己的版本。

public void DoSomething(ProcessingMethod method)    {
   method.DoSomething();
}

答案 4 :(得分:0)

如何将处理逻辑委托给特定的子类? ProcessingMethod将有一些由每个子类实现的抽象方法。

public void DoSomething(ProcessingMethod method)
{
  method.Process();
}

public abstract class ProcessingMethod
{
  public abstract void Process();
}

public class Sequental : ProcessingMethod
{
  public override void Process()
  {
    // do something sequential
  }
}

public class Random : ProcessingMethod
{
  public override void Process()
  {
    // do something random
  }
}

答案 5 :(得分:0)

是的,这闻起来很糟糕。如果你想做一些平行的事情:

public class Parallel : ProcessingMethod{}

那么你将不得不改变很多代码。

答案 6 :(得分:0)

框架设计指南一书建议不要使用标记接口(可能是标记类),而是选择属性intead。话虽如此,本书继续说明使用is(正如你所做的)比使用反射检查属性要快得多。