使用OOP在抽象逻辑中正确处理类型依赖性逻辑(高度多态对象)



从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());

这是我即时写的一个过分简化的示例。有一些可以改进的事情。这只是为了说明这一点。

最新更新