Как избежать дублирования кода при анализе двух разных объектов из файла? - PullRequest
0 голосов
/ 17 октября 2019

Я хочу проанализировать CSV-файл, как показано ниже. Файл CSV содержит два разных типа: Планета и Астероид. Оба эти типа имеют некоторые уникальные свойства. enter image description here

Я создал класс Planet и класс Asteroid, которые оба наследуют от абстрактного класса SpaceObject. Я создал класс Parser, который анализирует мой CSV-файл в списке объектов SpaceObject. К сожалению, мой класс содержит повторяющийся код, и это то, чего я пытаюсь избежать.

Мой код:

switch (ReadStringFromCellBasedOnHeader("type"))
{
    case "Asteroid":
        var asteroid = new Asteroid();
        asteroid.Position = new Vector2D(ReadDoubleFromCellBasedOnHeader("x"), ReadDoubleFromCellBasedOnHeader("y"));
        asteroid.Speed = new Vector2D(ReadDoubleFromCellBasedOnHeader("vx"), ReadDoubleFromCellBasedOnHeader("vy"));
        asteroid.Radius = ReadDoubleFromCellBasedOnHeader("radius");
        asteroid.Color =
            (Color?)ColorConverter.ConvertFromString(ReadStringFromCellBasedOnHeader("color")) ?? Color.FromRgb(0, 0, 0);
        break;
    case "Planet":
        var planet = new Planet();
        planet.Name = ReadStringFromCellBasedOnHeader("name");
        planet.Position = new Vector2D(ReadDoubleFromCellBasedOnHeader("x"), ReadDoubleFromCellBasedOnHeader("y"));
        planet.Speed = new Vector2D(ReadDoubleFromCellBasedOnHeader("vx"), ReadDoubleFromCellBasedOnHeader("vy"));
        planet.Neighbours.AddRange(ReadStringFromCellBasedOnHeader("neighbours").Split(','));
        planet.Radius = ReadDoubleFromCellBasedOnHeader("radius");
        planet.Color =
            (Color?)ColorConverter.ConvertFromString(ReadStringFromCellBasedOnHeader("color")) ?? Color.FromRgb(0, 0, 0);
        break;
    default:
        throw new Exception("Unknown SpaceObject Type");
}

string ReadStringFromCellBasedOnHeader(string header)
{
    return fields[columnDictionary[header]];
}

double ReadDoubleFromCellBasedOnHeader(string header)
{
    return StringConverter.ToDouble(ReadStringFromCellBasedOnHeader(header));
}

Как вы можете видеть, мои объекты Planet и Asteroid абсолютно одинаковы, кромеэта Планета содержит два уникальных свойства (имя и соседи). Я думал об использовании шаблона Factory или Builder, но я не хочу создавать функцию с девятью параметрами. Как я могу избежать этого повторяющегося кода элегантным способом?

Ответы [ 2 ]

3 голосов
/ 17 октября 2019

Вы можете просто поместить их под переключатель:

SpaceObject spaceObject;

switch (ReadStringFromCellBasedOnHeader("type"))
{
    case "Asteroid":
        spaceObject = new Asteroid();
        break;
    case "Planet":
        var planet = new Planet();
        spaceObject = planet;
        planet.Name = ReadStringFromCellBasedOnHeader("name");
        planet.Neighbours.AddRange(ReadStringFromCellBasedOnHeader("neighbours").Split(','));
        break;
    default:
        throw new Exception("Unknown SpaceObject Type");
}

spaceObject.Position = new Vector2D(ReadDoubleFromCellBasedOnHeader("x"), ReadDoubleFromCellBasedOnHeader("y"));
spaceObject.Speed = new Vector2D(ReadDoubleFromCellBasedOnHeader("vx"), ReadDoubleFromCellBasedOnHeader("vy"));
spaceObject.Radius = ReadDoubleFromCellBasedOnHeader("radius");
spaceObject.Color =
    (Color?)ColorConverter.ConvertFromString(ReadStringFromCellBasedOnHeader("color")) ?? Color.FromRgb(0, 0, 0);

В качестве альтернативы, вы можете использовать вспомогательную функцию:

switch (ReadStringFromCellBasedOnHeader("type"))
{
    case "Asteroid":
        var asteroid = new Asteroid();
        DeserializeCommon(asteroid);
        break;
    case "Planet":
        var planet = new Planet();
        DeserializeCommon(planet);
        planet.Name = ReadStringFromCellBasedOnHeader("name");
        planet.Neighbours.AddRange(ReadStringFromCellBasedOnHeader("neighbours").Split(','));
        break;
    default:
        throw new Exception("Unknown SpaceObject Type");
}

void DeserializeCommon(SpaceObject spaceObject)
{
    spaceObject.Position = new Vector2D(ReadDoubleFromCellBasedOnHeader("x"), ReadDoubleFromCellBasedOnHeader("y"));
    spaceObject.Speed = new Vector2D(ReadDoubleFromCellBasedOnHeader("vx"), ReadDoubleFromCellBasedOnHeader("vy"));
    spaceObject.Radius = ReadDoubleFromCellBasedOnHeader("radius");
    spaceObject.Color =
        (Color?)ColorConverter.ConvertFromString(ReadStringFromCellBasedOnHeader("color")) ?? Color.FromRgb(0, 0, 0);.
}
3 голосов
/ 17 октября 2019

Перемещая дублированный код за пределы коммутатора:

SpaceObject spaceObject;
switch (ReadStringFromCellBasedOnHeader("type"))
{
    case "Asteroid":
        spaceObject = new Asteroid();
        break;
    case "Planet":
        var planet = new Planet()
        {
            Name = ReadStringFromCellBasedOnHeader("name"),
            Neighbours = new List<string>();    
        };
        planet.Neighbours.AddRange(
             ReadStringFromCellBasedOnHeader("neighbours").Split(','));
        spaceObject = planet;
        break;
    default:
        throw new Exception("Unknown SpaceObject Type");
}
spaceObject.Position = new Vector2D(ReadDoubleFromCellBasedOnHeader("x"), ReadDoubleFromCellBasedOnHeader("y"));
spaceObject.Speed = new Vector2D(ReadDoubleFromCellBasedOnHeader("vx"),ReadDoubleFromCellBasedOnHeader("vy"));
spaceObject.Radius = ReadDoubleFromCellBasedOnHeader("radius");
spaceObject.Color =
    (Color?) ColorConverter.ConvertFromString(ReadStringFromCellBasedOnHeader("color")) ?? Color.FromRgb(0, 0, 0);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...