从OOP点处理从游戏对象到Gamedto对象的映射的最佳方法是什么,考虑到游戏具有具有很多派生对象的属性记分板(超过15个)作为FootballScoreBoard,Formula1Scoreboard,BaseballScoreboard等?
只有在运行时间内,游戏内部的计分板类型是什么(任何运动)。Scorboardto拥有相应的FootballScoreBoardto,Formula1ScoreBoardto,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链条和开关式箱,因为这是OOP的不良习惯。
我看到的可能的解决方案:使用某种计分板parserfactory,根据记分牌类型,返回必要的记分板解析器。喜欢:
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)我仍然必须在解析器的解析方法内进行显式类型的转换,例如:
public class FootballScoreboardParser
{
public ScoreboardDto Parse(Scoreboard scoreboard)
{
var footballScoreboard = (FootballScoreboard) scoreboard;
return new FootballScoreboardDto() {/*...*/};
}
}
是否有更好的方法可以从高质量的OOP代码(无明确的类型转换和长时间IF-ELSE/SWITCH-CASE)中实施转换?也许有任何标准处理此类案件的方法?IOC的任何帮助?
您可以使用通用接口进行:
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());
这是我即时写的一个过分简化的示例。有一些可以改进的事情。这只是为了说明这一点。