逻辑现在是多态而不是开关,但如何构建? [英] Logic is now Polymorphism instead of Switch, but what about constructing?

查看:153
本文介绍了逻辑现在是多态而不是开关,但如何构建?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题具体涉及到C#,但是我也对C ++和Java的答案感兴趣(或者甚至有其他语言,如果他们有一些很酷)。



我正在使用我继承的C使用C#语法代码替换多态的switch语句。我一直困惑着创建这些对象的最佳方法。我有两种后退的方法,我倾向于使用。我想知道是否有其他可行的替代方案,我应该考虑或只是一个理智检查,我实际上是以合理的方式进行的。



通常使用的技巧:


  1. 使用一个全能的方法/类。这个类将使用一个switch语句来填充一个数据结构(很可能是一个Map)或者动态构造。

  2. 使用一个使用配置文件的盲目笨重的类并反映创建一个实例/代表/工厂/地图。然后以类似于上述方式使用地图。

  3. ???

有没有#3,#4 ...等,我应该强烈地考虑?






请注意,原始设计不是我的,我的时间是有限的,只要重写/重构整个事情。



以前的伪代码:

  public string [] HandleMessage对象输入){

对象解析器= null;
string command = null;
if(input为XmlMessage){
parser = new XmlMessageParser();
((XmlMessageParser)解析器).setInput(input);
command =((XmlMessageParser)解析器).getCommand();
} else if(input为NameValuePairMessage){
parser = new NameValuePairMessageParser();
((NameValuePairMessageParser)解析器).setInput(input);
command =((XmlMessageParser)解析器).getCommand();
} else if(...){
// blah blah blah
}

string [] result = new string [3];
switch(command){
caseAdd:
result = Utility.AddData(parser);
break;
caseModify:
result = Utility.ModifyData(parser);
break;
case ... // blah blah
break;
}
返回结果;
}

我打算用(替换其他对象很多重构)是这样的:

  public ResultStruct HandleMessage(IParserInput input){
IParser parser = this.GetParser(input.Type ); //类型或属性
映射< string,string> parameters = parser.Parse(input);
ICommand命令= this.GetCommand(parameters); //在将来,可能需要多个参数
return command.Execute(parameters); //找出要返回的对象。
}

问题是GetParser和GetCommand的实现应该是什么? >

在那里放置一个switch语句(或者是由switch语句组成的工厂的调用)似乎不是这样,解决了这个问题。我只是把交换机放在别的地方,这可能是不错的,因为它不再是我的主要逻辑。

解决方案

您可能希望将解析器实例化器放在对象本身上,例如,

  public interface IParserInput 
{
...
IParser GetParser()
ICommand GetCommand()
}

理论上,您的对象需要 GetParser 需要的任何参数。



会发生什么是对象本身将返回那些,并且您的代码会发生什么:

  public ResultStruct HandleMessage(IParserInput input )
{
IParser parser = input.GetParser();
Map< string,string> parameters = parser.Parse(input);
ICommand command = input.GetCommand();
return command.Execute(parameters);
}

现在这个解决方案并不完美。如果您无法访问 IParserInput 对象,则可能无法使用。但是至少提供关于适当处理程序的信息的责任现在与parsee有关,而不是处理程序,在这一点上似乎更为正确。


This question is specifically regarding C#, but I am also interested in answers for C++ and Java (or even other languages if they've got something cool).

I am replacing switch statements with polymorphism in a "C using C# syntax" code I've inherited. I've been puzzling over the best way to create these objects. I have two fall-back methods I tend to use. I would like to know if there are other, viable alternatives that I should be considering or just a sanity check that I'm actually going about this in a reasonable way.

The techniques I normally use:

  1. Use an all-knowing method/class. This class will either populate a data structure (most likely a Map) or construct on-the-fly using a switch statement.
  2. Use a blind-and-dumb class that uses a config file and reflection to create a map of instances/delegates/factories/etc. Then use map in a manner similar to above.
  3. ???

Is there a #3, #4... etc that I should strongly consider?


Some details... please note, the original design is not mine and my time is limited as far as rewriting/refactoring the entire thing.

Previous pseudo-code:

public string[] HandleMessage(object input) {

   object parser = null;
   string command = null;
   if(input is XmlMessage) {
      parser = new XmlMessageParser();
      ((XmlMessageParser)parser).setInput(input);
      command = ((XmlMessageParser)parser).getCommand();
   } else if(input is NameValuePairMessage) {
      parser = new NameValuePairMessageParser();
      ((NameValuePairMessageParser)parser).setInput(input);
      command = ((XmlMessageParser)parser).getCommand();
   } else if(...) {
      //blah blah blah
   }

   string[] result = new string[3];
   switch(command) {
      case "Add":
          result = Utility.AddData(parser);
          break;
      case "Modify":
          result = Utility.ModifyData(parser);
          break;
      case ... //blah blah
          break;
   }
   return result;
}

What I plan to replace that with (after much refactoring of the other objects) is something like:

public ResultStruct HandleMessage(IParserInput input) {
   IParser parser = this.GetParser(input.Type);       //either Type or a property
   Map<string,string> parameters = parser.Parse(input);
   ICommand command = this.GetCommand(parameters);  //in future, may need multiple params 
   return command.Execute(parameters);              //to figure out which object to return.
}

The question is what should the implementation of GetParser and GetCommand be?

Putting a switch statement there (or an invokation of a factory that consists of switch statements) doesn't seem like it really fixes the problem. I'm just moving the switch somewhere else... which maybe is fine as its no longer in the middle of my primary logic.

解决方案

You may want to put your parser instantiators on the objects themselves, e.g.,

public interface IParserInput
{
    ...
    IParser GetParser()
    ICommand GetCommand()
}

Any parameters that GetParser needs should, theoretically, be supplied by your object.

What will happen is that the object itself will return those, and what happens with your code is:

public ResultStruct HandleMessage(IParserInput input) 
{
    IParser parser = input.GetParser();
    Map<string,string> parameters = parser.Parse(input);
    ICommand command = input.GetCommand();
    return command.Execute(parameters);
}

Now this solution is not perfect. If you do not have access to the IParserInput objects, it might not work. But at least the responsibility of providing information on the proper handler now falls with the parsee, not the handler, which seems to be more correct at this point.

这篇关于逻辑现在是多态而不是开关,但如何构建?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆