Чтобы решить этот вопрос, сначала важно установить, что делает каждый компонент.
CCar - контейнер, содержащий компоненты и агрегаты.
CDriver - объект, представляющий драйвер
CEngine - объект, представляющий двигатель
и т.д.
Для небольшой и простой программы следует использовать упрощенную конструкцию, в которой водитель получает указатель на автомобиль
CCar( CDriver* pDriver )
{
m_pDriver = pDriver;
m_pDriver->SetCar(this);
}
Для более масштабного применения это недопустимо, когда CCar может потребовать добавления новых компонентов и т. Д., И было бы плохой практикой проектирования предоставлять водителю доступ ко всему CCar - здесь водитель сможет менять не только рулевое управление колесо, но цвет машины и т. д., что явно не намерение.
Как насчет предоставления драйверу доступа к нужным битам?
m_pDriver->SetSteeringWheel( m_SteeringWheel );
m_pDriver->SetHandBrake( m_HandBrake );
это решает эту проблему, теперь водитель не имеет доступа к другим атрибутам машины (например, цвету). Тем не менее, это дает классу CDriver больше обязанностей. Там, где CDriver может использовать множество элементов управления, класс может стать очень большим и несет ответственность за управление этими объектами рулевого колеса и ручного тормоза. Что делать, если водитель садится в другой тип автомобиля, который не имеет такого же управления, как другие? Теперь водитель должен выяснить, как управлять транспортным средством с помощью имеющихся у него органов управления? Лишняя логика Extra 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 );
}