Неисправность, избегающая последовательности Loop-switch - PullRequest
2 голосов
/ 11 декабря 2011

Я новичок в Android / Java, не столько с кодированием, сколько с языками.

Моя проблема:

Я рисую график (для некоторого статистического анализа) с canvas.drawLine() разными цветами для каждой линии. Цвет зависит от значения массива. Этот массив (список) содержит пользовательские объекты, которые имеют около 20 переменных разных типов.

В какой-то момент мне нужен переключатель, чтобы получить правильный тип для каждого вызова отрисовки, но для всего цикла этот переключатель имеет тот же результат. Поскольку я почти закончил с программой, я ищу проблемы с производительностью, и это одна. График рисует не менее 1000 линий, поэтому коммутатор работает 1000 раз для того же результата.

Если бы у меня были массивы, а не пользовательские объекты, я мог бы просто использовать int для доступа к различным значениям массива. Но нет способа переписать его так, чтобы можно было избежать объектов (это могло бы испортить код в других местах).

Теперь я читаю о полиморфизме и отражениях, но ... Честно говоря, я не хочу реализовывать то, что не до конца понимаю, и которое не является пуленепробиваемым (говорят, что отражения подвержены ошибкам?!)

Мое текущее решение заключается в том, что я просто создал собственный метод рисования для каждого случая. У меня есть один переключатель перед циклом, а затем работает метод рисования с правильным получателем. Это работает, однако кажется безумным иметь 10 методов только с одной строкой.

Теперь есть и абстрактные классы, но меня это немного смущает, и мне интересно, не вызовут ли эти перезаписанные методы больше проблем с производительностью, чем коммутатор. Я прочитал кое-что о том, что делает Java в конце, и что эти вызовы методов между классами могут стоить производительности (я признаю, что это было что-то из внутренних / вложенных классов, вызывающих получатель их внешнего класса).

Я хочу, чтобы код был как можно более коротким и читаемым, поэтому я хотел бы, чтобы все это было в одном кодовом блоке (вроде), а не распространялось на разные классы, но это всего лишь личное предпочтение. Самое главное, что я полностью понимаю, что я реализую. Я не хочу, чтобы какой-то пример я копировал и вставлял с помощью команды «введите свой метод» и вижу, как он работает, но не знаю, почему и как.

Так что на самом деле меня больше интересует теоретическое, как я должен это делать, чем реальные фрагменты кода (ofc фрагменты не повредят;))

PS: Если у меня где-то есть запах кода, не стесняйтесь упоминать об этом.

Какой-то код, просто выложенный и сфокусированный на проблеме

Class MyObj {

  int x;
  int y;

  double value_doub;
  short value_short;

  // getters and setters etc
}


private void draw_graph(int switchcase) {
  MyObj mObj;
  int x;
  int y;
  double value;

  for(int i = 0; i < amount_of_values; i++) {

    mObj = mArrayList.get(i);

    x = mObj.getx();
    y = mObj.gety();

    switch(switchcase) {

    case 0:
      value = mObj.get_value_doub();

      //alternatively, direct field access
      value = mObj.value_doub;

      color = calc_color(value, scale_for_this_type);
    break;

    case 1:
      value = (double) mObj.get_value_short();

      //alternatively, direct field access
      value = (double) mObj.value_short;

      color = calc_color(value, scale_for_this_type);
    break;

    // etc...  10+ cases
    }


  drawLine(last_x, last_y, x, y, color);

  }
}

Ответы [ 2 ]

1 голос
/ 11 декабря 2011

Ваш код в порядке, но не очень объектно-ориентированный. Я бы, вероятно, использовал какой-нибудь интерфейс Drawer и передал бы подходящую реализацию, а не int, методу draw_graph (который я бы переименовал в drawGraph для соблюдения соглашений об именах):

public interface Drawer {
    void draw(MyObj obj, Graphics g);
}

...

private void drawGraph(Drawer drawer) {
    for(int i = 0; i < amountOfValues; i++) {
        MyObj obj = arrayList.get(i);
        drawer.draw(obj, g);
    }
}

...

class Drawer1 implements Drawer {
    @Override
    public void draw(MyObj obj, Graphics g) {
        // same code as in case 1 of the switch
    }
}
class Drawer2 implements Drawer {
    @Override
    public void draw(MyObj obj, Graphics g) {
        // same code as in case 2 of the switch
    }
}

Если все ящики разделяют некоторый код, тогда заставьте их расширять базовый класс AbstractDrawer.

0 голосов
/ 12 декабря 2011

x, y и значение являются свойствами MyObj.Что делает calc_color и откуда берется scale_for_this_type?Может ли эта работа выполняться внутри или в основном внутри MyObj на основе его полей?Если это так, ваш цикл может в значительной степени вызвать myObj.drawLineYouFigureOutTheColor (возможно, AnArgumentOrTwoHere).Вы должны были бы где-то отслеживать last_x и last_y.

...