从OOP的角度来处理从Game对象到GameDto对象的映射的最佳方法是什么,考虑到Game的属性Scoreboard有很多派生对象(超过15个)作为FootballScoreboard,Formula1Scoreboard,BaseballScoreboard等?
只有在运行时才有能力知道游戏内部的记分板的确切类型(它可以用于任何运动)。 ScoreboardDto有相应的FootballScoreboardDto,Formula1ScoreboardDto,BaseballScoreboardDto等等。
简化方案:
public class Game
{
public Scoreboard Scoreboard { get; }
}
public class GameDto
{
public ScoreboardDto Scoreboard { get; }
}
public class DtoParser
{
public GameDto Parse(Game game)
{
var gameDto = new GameDto();
//How to implement parsing of game.Scoreboard in the best way here????
}
}
主要目标是避免if-else链和switch-case,因为它在OOP中是不好的做法。
我看到的可能的解决方案: 使用某种ScoreboardParserFactory,根据记分牌类型返回必要的记分板解析器。 像:
var parser = _scoreboardParserFactory.Create(game.Scoreboard);
gameDto.Scoreboard = parser.Parse(game.Scoreboard);
但仍有缺点:
1)看起来我仍然不能仅使用IoC进行任何实现,而且不需要if-else / switch-case,如下所示:
if (scoreboard.GetType() == typeof(FootballScoreboard)) return new FootballScoreboardParser()
else if (scoreboard.GetType() == typeof(Formula1Scoreboard)) return new Formula1ScoreboardParser()
else ...
2)我仍然需要在解析器的Parse方法中进行显式类型转换,如:
public class FootballScoreboardParser
{
public ScoreboardDto Parse(Scoreboard scoreboard)
{
var footballScoreboard = (FootballScoreboard) scoreboard;
return new FootballScoreboardDto() {/*...*/};
}
}
有没有更好的方法来实现高质量OOP代码的转换(没有明确的类型转换和长if-else / switch-case)?也许有任何标准的处理此类案件的方法? IoC对此有何帮助?
答案 0 :(得分:0)
您可以使用通用接口来实现:
public class DtoParserFactory
{
private Dictionary<Type, IDtoParser> _parsers = new Dictionary<Type, IDtoParser>();
public void Register(Type type, IDtoParser parser)
{
_parsers.Add(type, parser);
}
public IDtoParser GetParser(IScoreBoard scoreBoard)
{
var type = scoreBoard.GetType();
var parser = _parsers[type];
return parser;
}
}
public class SomeScoreboardParser : BaseScoreBoardParser<SomeScoreboard, ScoreboardDto>
{
public override ScoreboardDto Parse(SomeScoreboard scoreBoard)
{
return new ScoreboardDto();
}
}
public abstract class BaseScoreBoardParser<TScoreBoard, TDto> : IDtoParser<TScoreBoard, TDto> where TScoreBoard : IScoreBoard where TDto: IDto
{
public abstract TDto Parse(TScoreBoard scoreBoard);
public IDto Parse(IScoreBoard scoreBoard)
{
return Parse((TScoreBoard)scoreBoard);
}
}
public interface IDtoParser<TScoreBoard, TDto> : IDtoParser
where TScoreBoard : IScoreBoard
where TDto : IDto
{
TDto Parse(TScoreBoard scoreBoard);
}
public interface IDtoParser
{
IDto Parse(IScoreBoard scoreBoard);
}
public class ScoreboardDto : IDto
{
}
public interface IDto
{
}
然后消耗它:
var game = new Game();
DtoParserFactory factory = new DtoParserFactory();
factory.Register(typeof(SomeScoreboard), new SomeScoreboardParser());
var parser = factory.GetParser(game.Scoreboard);
var dto = parser.Parse(game.Scoreboard);
您只需在工厂注册您的类型,它就会为您解决。这是在代码示例中执行此操作的行:
factory.Register(typeof(SomeScoreboard), new SomeScoreboardParser());
这显然是我在飞行中写的一个过于简单的例子。有一些事情可以改进。这只是为了说明这一点。