2009-05-31 5 views
2

Я создаю объекты для моделирования с использованием агрегации и композиции.Управление отношениями между агрегированными/скомпонованными членами класса

В следующем примере C++:

class CCar 
{ 
    CCar(CDriver* pDriver) 
    { m_pDriver = pDriver; } 

    CDriver* m_pDriver; 

    CEngine m_Engine; 

    CDriverControls m_Controls; 
}; 

в приведенном выше примере, машина состоит из двигателя и набора приводных элементов управления (по составу). Автомобиль также должен иметь водителя (путем агрегации).

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

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

спасибо!

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

, как ответы говорят, один из способов справиться с этим через указывая автомобиль с водителем, и дает водителю указатель на автомобиле, и т.д. Это имеет смысл, и решает этот конкретный пример , Однако в конструктивном смысле это повышает ответственность водителя, когда этому объекту поручается отслеживать, к какому автомобилю он принадлежит, но, конечно же, обязанность контейнера отслеживать, какие объекты принадлежат друг другу? Аналогично, задача CCar с управлением этими отношениями превратит CCAR в blob. Есть ли разработанное решение для решения этих отношений?

ответ

1

Вы создаете их в методах каждого класса. То, что вы описываете, - это поведение каждого класса. Ваши требования предполагают, что отношения также двунаправлены. Класс Controls будет иметь методы, которые принимают параметр Engine и вызывают его методы. Двигатель будет иметь ограничения на его RPM, HP, крутящий момент и т. Д., Управляемые Control, которые будут иметь встроенные в них лимиты (например, «Если ваш RPM падает слишком низко, остановитесь»).

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

0

Вы, вероятно, хотите двухстороннюю связь между автомобилем и водителем:

CCar(CDriver* pDriver) : 
    m_pDriver(pDriver) 
{ 
    m_pDriver->SetCar(this); 
} 

Затем водитель может получить доступ к членам автомобиля через открытый интерфейс автомобиля.

1

Вопрос должен состоять в том, «должно ли мое приложение нуждаться в этих отношениях?» Например, если вы моделируете рулевое управление автомобилем для простой вождения, вам, вероятно, вообще не нужно беспокоиться о двигателе для люка крыши. Рулевому колесу может потребоваться знать, что он подключен к дорожным колесам, но нет необходимости в обратной связи.

Нижняя линия - в реальном мире все связано, но в компьютерных моделях мы создаем этот мир для решения конкретных проблем, это не так.

+0

благодарит за ответ. приведенный пример - это действительно пример (хотя, вероятно, он мог бы использовать и лучший!), Но я пытался проиллюстрировать проблему, с которой я столкнулся. Я на самом деле не пишу программу о машинах и драйверах. – 2009-05-31 17:19:02

1

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

Ваши реализации могут использовать состав, агрегацию и наследование. Но в этом подходе это действительно интерфейсы, которые управляют дизайном. Используете ли вы состав, агрегацию или наследование в данном экземпляре, это просто детализация реализации.

+0

thankyou, это отличное начало для меня, чтобы решить это. – 2009-06-01 12:23:19

0

Чтобы решить этот вопрос, важно сначала установить, что делает каждый компонент.

CCar - контейнер, содержащий компоненты и агрегаты.

CDriver - объект, представляющий водителю

CEngine - объект, представляющий собой двигатель

т.д.

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

для большего применения это неприемлемо, когда CCAR может потребовать новых компонентов AddIn g и т. д., и было бы плохой проектной практикой предоставить драйверу доступ ко всей CCar - здесь водитель сможет изменить не только руль, но и цвет автомобилей и т. д., что явно не является намерением.

А как же просто предоставить драйверу доступ к битам, в которых он нуждается?

m_pDriver->SetSteeringWheel(m_SteeringWheel); 
m_pDriver->SetHandBrake(m_HandBrake); 

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

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

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

Посредник несет ответственность за обработку этой взаимосвязи между компонентами.

class CMediatorDriverToSteeringWheel 
{ 
CMediatorDriverToSteeringWheel(CDriver* pDriver, CSteeringWheel* pSteeringWheel) 
{ 
m_pDriver = pDriver; 
m_pSteeringWheel = pSteeringWheel; 
m_pDriver->AddMediator(this); 
m_pSteeringWheel->AddMediator(this); 
} 
}; 

... 

CCar::CCar(CDriver* pDriver) 
{ 
m_pDriver = pDriver; 
new CMediatorDriverToSteeringWheel(m_pDriver, &m_SteeringWheel); 
new CMediatorDriverToHandbrake(m_pDriver, &m_HandBrake); 
} 
+0

благодаря всем остальным ответам, вы все внесли большой вклад, который помог мне задуматься над моим вопросом, но никакой ответ действительно не охватывал всю проблему. Я продолжал исследования и считаю, что это наиболее релевантный ответ. Я по-прежнему открыт для других решений (как я уверен, их много), поэтому, пожалуйста, дайте больше ответов, если вы считаете, что у вас есть лучшее решение! – 2009-06-02 13:42:34

 Смежные вопросы

  • Нет связанных вопросов^_^