Рубрики
Без рубрики

Эффективная Java! Предпочитайте Иерархии классов помеченным классам

Погружение в главу 23 Эффективной Java. Помеченный java, эффективный, интерфейсы, архитектура.

Эффективный обзор Java (Серия из 78 частей)

Похоже, что многие предыдущие главы Эффективная Java разделяли некоторые опасения по поводу использования всех возможностей, которые предлагает нам объектно-ориентированное программирование. Действительно, существуют подводные камни, связанные с чрезмерным использованием некоторых функций этих шаблонов, поэтому их следует использовать с осторожностью. Однако сегодня мы рассмотрим тему, в которой объектно-ориентированное программирование может прийти на помощь.

Давайте начнем с рассмотрения следующего класса.

class Figure {
  enum Shape {CIRCLE, RECTANGLE}

  final Shape shape;
  double length;
  double width;

  double radius;

  Figure(double radius) {
    shape = Shape.CIRCLE;
    this.radius = radius;
  }

  Figure(double length, double width) {
    shape = Shape.RECTANGLE;
    this.length = length;
    this.width = width;
  }

  double area() {
    switch(shape) {
      case RECTANGLE:
        return length * width;
        break;
      case CIRCLE:
        return Math.PI * (radius * radius);
        break;
      default:
        throw new AssertionError(shape);
    }
  }
}

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

  • Существует много шаблонных шаблонов.
    • Везде, где мы имеем дело со значениями и тем, как их нужно по-разному обрабатывать между помеченными типами, потребуется какой-то утомительный шаблон. Это приведет к значительному снижению читабельности.
  • Объем памяти увеличивается, так как все экземпляры класса будут обременены ненужными значениями.
  • Класс нельзя сделать неизменяемым, так как поля нельзя сделать окончательными если только конструкторы не инициализируют нерелевантные значения.
  • Мы также теряем некоторые преимущества нашего компилятора, поскольку класс с тегами не использует все поля вместе.

Так каков же ответ? К счастью, объектно-ориентированное программирование дает ответ с помощью иерархий классов. Как мы можем превратить помеченные классы в иерархию классов? Первым шагом является создание общего абстрактного класса, в котором хранятся общие переменные и абстрактные объявления общих методов. В нашем классе Figure есть только один общий метод, метод area . Затем мы должны создать класс, который расширяется от корневого абстрактного класса для каждого из типов, имеющих тег. Давайте посмотрим, как наш Рисунок можно было бы изменить, чтобы следовать этому методу:

abstract class Figure {
  abstract double area();
}

class Rectangle extends Figure {
  final double width;
  final double length;

  Rectangle(double width, double length) {
    this.width = width;
    this.length = length;
  }

  @Override
  double area() {
    return width * length;
  }
}

class Circle extends Figure {
  final double radius;

  Circle(double radius) {
    this.radius = radius;
  }

  @Override
  double area() {
    return Math.PI * (radius * radius);
  }
}

Несмотря на то, что в этом примере мы получаем больше классов, каждый класс намного проще, понятнее и эффективнее. Теперь давайте подумаем, нужно ли нам добавлять новый тип:

class Square extends Rectangle {
  Square(double side) {
    super(side, side);
  }
}

Так же просто добавить новый тип. Представьте, как это выглядело бы в примере с помеченным классом. В то время как это очень чисто, помеченный класс стал бы только более сложным и менее простым.

Как вы можете видеть, на самом деле нет никаких преимуществ использования помеченных классов вместо правильной иерархии классов. Если вы подумываете об использовании помеченного класса, пересмотрите свое решение и подумайте, как вместо этого можно использовать иерархию классов. Это приведет к более эффективному, простому в обслуживании и менее подверженному ошибкам коду.

Эффективный обзор Java (Серия из 78 частей)

Оригинал: “https://dev.to/kylec32/effective-java-prefer-class-hierarchies-to-tagged-classes-59l9”