C# 使用标记类控制逻辑流
我一直在浏览一些代码,看到我的一位同事正在使用“标记类”来控制程序逻辑(参见下面的人为示例)。它似乎工作得很好,代码读起来也很好,但它只是有点异味C# 使用标记类控制逻辑流,c#,.net,C#,.net,我一直在浏览一些代码,看到我的一位同事正在使用“标记类”来控制程序逻辑(参见下面的人为示例)。它似乎工作得很好,代码读起来也很好,但它只是有点异味 namespace ConsoleApplication4983 { public class MyClass { static void Main() { var c = new MyClass(); c.DoSomething(new Sequenti
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() { }
}
}
他几乎就在那里,但不完全在那里,这可能就是你所看到的。类型上的if语句是臭味。do something应该在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{}
然后,您将不得不更改许多代码 您要做的是将其替换为一个。策略定义了如何完成某件事,即算法
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 method的代码。框架设计指南书建议不要使用标记接口(可能还有标记类),首选属性intead。话虽如此,这本书还是继续说,使用
is
(正如您所做的)比使用反射检查属性要快得多。我看到这个问题很老,但我觉得所有的答案都没有抓住重点
如果该示例充分说明了所需功能的范围,那么此处使用的适当构造将是枚举类型。枚举类型是值类型;它们的功能本质上类似于命名的数值常量,具有强大的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
}
}
其他答案是参考更复杂的模式。我认为他们对“标记类”这个词读得太多了。有时,策略模式、虚拟调度等是一种很好的方法,但在这种情况下,我认为枚举是对代码进行的最简单的改进