Объектно-ориентированный дизайн - формы - PullRequest
0 голосов
/ 11 июня 2018

Итак, после многих лет ООП, я получил довольно простое домашнее задание на одном из моих университетских курсов для реализации простой объектно-ориентированной структуры.

Запрошенный дизайн:

  • Реализовать объектно-ориентированное решение для создания следующих фигур:

  • Эллипс, Круг, Квадрат, Прямоугольник, Треугольник, Параллелограмм.

  • Каждая созданная фигура должна иметь следующие параметры : уникальный идентификатор, цвет.

И следующие функции :изменение цвета, перемещение, площадь, окружность, внутри, копирование.

Проверка достоверности не требуется (не в классах и не из ввода пользователя).

Мой дизайн :

enter image description here

В целом довольно простой подход, shape_class / non-round являются абстрактными, а прямоугольник / квадрат объединяются в один класс, поскольку содержат точноодни и те же параметры и тесты на валидность не требуютсяn, чтобы разделить их на две части).

Класс Shape - реализует статический идентификатор (уникальный идентификатор) и функцию init, имеющую дело с именем цвета.

public abstract class shape_class {

    static int STATIC_ID;
    int id;
    String color_name;

    public shape_class(String color_name_input) {
        this.id = STATIC_ID;
        shape_class.STATIC_ID+=1;
        if (Arrays.asList(toycad_globals.ALLOWED_COLORS).contains(color_name_input))
        {
            this.color_name = color_name_input;
        }
    }

    public void change_color(String color_name_input) {
        if (Arrays.asList(toycad_globals.ALLOWED_COLORS).contains(color_name_input)) {
            this.color_name = color_name_input;
        }
    }

    public abstract shape_class return_copy();
    public abstract void move(double x, double y);
    public abstract double area();
    public abstract double circumference();
    public abstract boolean is_inside(double x, double y);
}

** Некруглый ** - Получает массив точек (которые определяют объект) и реализует почти все необходимые функции.

public abstract class non_circullar extends shape_class {
    List<line> line_list = new ArrayList<line>();
    List<point> point_list = new ArrayList<point>();

    non_circullar(String color_name, point...input_point_list) {
        super(color_name);
        this.point_list = Arrays.asList(input_point_list);
        for (int current_index =0; current_index< (input_point_list.length); current_index++) {
            point current_first_point = input_point_list[current_index];
            point current_second_point = input_point_list[(current_index+1)%input_point_list.length];
            this.line_list.add(new line(current_first_point, current_second_point));
        }
    }

    public point[] get_point_list_copy() {
        int index = 0;
        point [] new_array = new point[this.point_list.size()];
        for (point current_point:this.point_list) {
            new_array[index] = current_point.return_copy();
            index+=1;
        }
        return new_array;
    }

    public double circumference() {
        double sum = 0;
        for (line current_line :this.line_list) {
            sum += current_line.get_length();
        }
        return sum;
    }

    public void move(double x, double y) {
        for (point current_point :this.point_list) {
            current_point.move(x, y);
        }
    }

    public boolean is_inside(double x, double y) {
        int i;
        int j;
        boolean result = false;
        for (i = 0, j = this.point_list.size() - 1; i < this.point_list.size(); j = i++) {
            if ((this.point_list.get(i).y > y) != (this.point_list.get(j).y > y) &&
                (x < (this.point_list.get(j).x - this.point_list.get(i).x) * (y - this.point_list.get(i).y) / 
                        (this.point_list.get(j).y-this.point_list.get(i).y) + this.point_list.get(i).x)) 
           {
              result = !result;
           }
        }
        return result;
    }

    int get_top_left_line_index() {
        int top_left_line_index = 0;
        int index = 0;
        point best_point = this.line_list.get(0).get_average_point();
        point current_point;
        for (line current_line :this.line_list) {
            current_point = current_line.get_average_point();

            if (current_point.x < best_point.x) {
                best_point = current_point;
                top_left_line_index = index;
            } else if (current_point.x == best_point.x && current_point.y > best_point.y) {
                best_point = current_point;
                top_left_line_index = index;
            }
            index +=1;
        }
        return top_left_line_index;
    }
}

Задача:

За это задание было уменьшено 40 баллов за вопросы проектирования:

1) Круг - это эллипс и, следовательно, необходимонаследовать от него (даже если они не имеют общих параметров).

2) Прямоугольник / квадрат - это две разные сущности, даже если в этой реализации они абсолютно одинаковы (без проверок достоверности).

Я был бы рад получить от сообщества некоторую информацию об этом дизайне, являются ли проблемы дизайна «законными» или нет, и что можно было бы сделать лучше?

Редактировать 1:

Эллипс выражается как: две точки и d (для того, чтобы точка находилась на эллипсе, расстояние между ней и двумя точками должно быть равно d).

Круг выражается как:центр и радиус.

Мне очень трудно понять, как они могут иметь общие параметры.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Дизайн, который вы использовали, не является идеей (ИМХО).

Сначала переименуйте non-circular в Polygon (также используйте заглавные буквы для первой буквы).

На основереализация, Circle - это конкретная Ellipse, поэтому я бы использовал здесь наследование

Shape < -- Circular < -- Ellipse < -- Circle
      < -- Polygon < -- Triangle      < -- Equilateral
                                      < -- ... //don't know the english names of those triangles 
                   < -- Quadrilateral < -- Square
                                      < -- Rectangle
                                      < -- ...
                   < -- Hexagon
                   < -- ...

Каждый подкласс Polygon является абстрактным, они используются для проверки количества углов.

В общем, я бы связал Square и Rectangle на основе правила геометрии (одинаковой ширины и высоты) (Square extends Rectangle), но на основе вашей реализации с использованием Point и Line,это не обязательно.
Но использование двух классов все еще допускает некоторую проверку в будущем (каждый Line для квадрата должен иметь одинаковую длину, ...).

Это показывает, что дизайн в основном зависит от требований, а не только от предмета.

О Ellipse и Circle.Ellipse - это форма двух точек, если эти точки совпадают, это Circle, это может быть ссылка;)

enter link description here

0 голосов
/ 11 июня 2018

Я предлагаю вам придерживаться этой схемы:

enter image description here

Сначала необходимо классифицировать фигуры по количеству ребер, а затем по общим характеристикам.Затем вы должны признать следующие факты:

  • circle - это просто особый тип ellipse
  • square - это просто особый тип rectangle
  • оба rectangle и parallelogram имеют 4 ребра
  • в отличие от parallelogram, rectangle имеют все углы 90 °.

Это упрощенная схема в соответствии с вашими потребностями:

Эллипс, Круг, Квадрат, Прямоугольник, Треугольник, Параллелограмм

Редактировать: Примечаниечто существует также следующая иерархия.И rectangle, и parallelogram имеют противоположные края одинаковой длины.Наконец, это зависит от предпочтительной интерпретации и от того, что лучше подходит для вашей ситуации (благодаря @Federico klez Culloca):

Quadrilateral <- Parallelogram <- Rectangle <- Square

Сделать его масштабируемым: В случае более сложных форм элементарныхвключая геометрию, я бы поставил, вероятно, место polygon ниже shape, а затем сначала дифференцировал потомков по выпуклости и невыпуклости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...