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

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

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 {} } 

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

标记界面是一种更好的实践,因为它们提供了更大的灵活性。

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

 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() { } } } 

你想要做的是用策略模式替换它。 策略定义了某些事情是如何完成的 – 即算法。

 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方法的代码。

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

如果该示例完全说明了所需function的范围,那么此处使用的适当构造将是Enum类型 。 枚举类型是值类型; 它们的function与命名数值常量基本相同,具有出色的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是对这段代码最简单的改进。

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

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

如何将处理逻辑委托给特定的子类? 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 } } 

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

 public class Parallel : ProcessingMethod{} 

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

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