Шаблон проектирования для обработки групп объектов - PullRequest
0 голосов
/ 17 октября 2019

У меня есть класс item. Каждый экземпляр этого класса является объектом в трехмерном пространстве и может иметь базовые формы, такие как цилиндр , сфера и конус . class Item имеет удобный API для геометрии (радиус, верхний радиус, радиус бота, длина) и преобразований (вращение, перемещение, масштаб).

enum ItemType {
    Sphere = 1,
    Cone
}

class Item
{
// ...
public:
    ItemType type();
    void setType(const ItemType &t);

    float radius();
    float length();
    float topRadius();
    float botRadious();
    QMatrix4x4 transformations();

    void setRadius(const float &r);
    void setLength(const float &l);
    void setTopRadius(const float &tr);
    void setBotRadius(const float &br);
    void setTransformations(const QMatrix4x4 &matrix);
// ...
}

Class instances as 3D items

Часто я хочу склеить несколько объектов, чтобы сформировать единую форму. Например, две сферы и конус соединены ниже. Геометрия и преобразования объединенного объекта зависят от геометрии двух сфер и одного конуса .

Three objects Three objects unified

Проблема в следующем:

  1. Удобная обработка объединенного объекта невозможна
  2. Под обработкой я подразумеваю, например, преобразование. Как и при изменении длины унифицированного объекта, что требует изменения длины среднего конуса и расположения двух сфер соответственно.
  3. class Item имеет API для удобной обработки каждого отдельного объекта, но не унифицированный
  4. Для работы с унифицированным объектом мне нужно работать с тремя разными объектами, которые являются мучительными

Вопрос:

Какие шаблоны проектирования лучше всего подходят дляудобно обращаться с унифицированными предметами?

Ответы [ 2 ]

1 голос
/ 18 октября 2019

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

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

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

Итак, что вам в первую очередь нужно сделать, это извлечь истинный интерфейс для того, что вы называете «API». Я бы назвал это Primitive3D, и это будет class, не содержащий ничего, кроме чисто виртуальных методов. (В C ++ это будет virtual function(parameters) = 0.)

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

Затем введите новый примитив, который называется возможно Conglomerate. Опять же, это был бы еще один класс, реализующий Primitive3D. Этот класс предоставит свои собственные реализации для установки различных атрибутов, таких как длина и преобразование, и эти реализации будут работать, устанавливая некоторые атрибуты содержащихся примитивов.

Класс Conglomerate также будет предоставлять несколько функций, которыеспецифичные для него и не могут быть найдены в интерфейсе Primitive3D. Эти функции можно использовать для настройки конгломерата, по крайней мере, для заполнения конгломерата его содержимым.

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

Внутренне конгломерация, вероятно, будет использовать vector содержащий экземпляры некоторой внутренней member структуры, которая будет содержать ссылку на Primitive3D и любую другую информацию, необходимую для того, чтобы знать, как обрабатывать этот примитив. Не делайте ошибку, добавляя эту информацию к самому Primitive3D, она там не принадлежит, потому что примитив не знает и не должен знать, что он является членом конгломерата. Я бы даже сказал, что местоположение примитива не является особенностью самого примитива;это особенность пространства, содержащего примитив, будь то пространство вселенной или конгломерат.

...