Я оцениваю стратегии реализации для модели наблюдателя, и одно из требований — для базы Subject
класс для достижения метода в производном (конкретном) классе Event
учебный класс.
В реализации прототипа я достиг этого кода в конкретном классе событий:
// a concrete event
class evZoom : public AbstractEvent
{
public:
virtual void Fill( Subject *aZoomManager)
{
mRatio = dynamic_cast<ZoomManager *>(aZoomManager)->mRatio;
}
int mRatio;
};
Теперь меня беспокоит тот факт, что каждое конкретное событие должно выполнять приведение этого типа.
Другими словами, я забочусь о простоте и краткости кода, где я бы предпочел конкретные классы (которых их много), чтобы иметь более элегантный код, торгуемый с помощью более сложного кода базового класса (для которого он есть).
Поэтому решение, которое я придумала, заключается в использовании шаблона-посредника (т. Е. Между базовым классом и конкретным классом) для выполнения типизации.
Полная реализация выглядит так:
// For Dec
class Subject;
// A non template abstract base class for the Subject class to work with.
class AbstractEvent
{
public:
virtual void Fill ( Subject *aSubject ) = 0;
};
// A mediator class to do the type casting
template < class TSubject >
class Event : public AbstractEvent
{
public:
// This is where we do the type cast.
virtual void Fill ( Subject *aSubject )
{
TSubject *iSubject = dynamic_cast<TSubject *>(aSubject);
// Somehow the compiler knows to call the abstract method below, but if
// we change its name we'll get an infinite loop - cranky.
Fill( iSubject );
}
// And a new abstract method to be implemented by concrete events.
virtual void Fill ( TSubject *aSubject ) = 0;
};
// The subject base class
class Subject
{
public:
// virtual destructor to make this class polymorphic
// so we can cast it dynamically.
virtual ~Subject() { }
void Subscribe( AbstractEvent *aEvent )
{
aEvent->Fill( this );
}
};
// A concrete subject class.
class ZoomManager : public virtual Subject
{
public:
int mRatio;
};
// The concrete event
class evZoom : public Event< ZoomManager >
{
public:
virtual void Fill( ZoomManager *aZoomManager )
{
mRatio = aZoomManager->mRatio;
}
int mRatio;
};
int main(int argc, const char * argv[])
{
ZoomManager iZoomManager;
evZoom *iEvent = new evZoom();
iZoomManager.Subscribe( iEvent );
return 0;
}
Единственная проблема с этим заключается в том, что у меня есть внутреннее чувство, что есть лучшее решение; во многом, поскольку я не помню, чтобы когда-либо видел класс-посредник, подобный тому, что был выше, в каком-либо источнике или библиотеке — но это может быть моей неопытностью.
Может ли кто-нибудь посоветовать лучшее решение выше?
Задача ещё не решена.
Других решений пока нет …