0

我正在评估观察者模式的实现策略,其中一个要求是基Subject类能够到达类的派生(具体)类中的方法Event

在原型实现中,我在具体事件类中达到了这个代码:

// a concrete event
class evZoom : public AbstractEvent
{
public:
    virtual void Fill( Subject *aZoomManager)
    {
        mRatio = dynamic_cast<ZoomManager *>(aZoomManager)->mRatio;
    }

    int mRatio;
};

现在我对每个 concreate 事件都必须执行这种类型转换这一事实感到困扰。

换句话说,我关心代码的简单性和简洁性,我宁愿使用具体的类(其中有很多)来拥有更优雅的代码,并用更复杂的基类代码(有一个)进行交易。

所以我想出的解决方案是使用中介(即基类和具体类之间的一个)模板来进行类型转换。

完整的实现如下所示:

// 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;
}    

唯一的问题是我有一种直觉,认为有更好的解决方案。主要是因为我不记得曾经在任何来源或库中看到过像上面那样的中介类 - 但可能是我的经验不足。

有人可以就上述问题提出更好的解决方案吗?

4

0 回答 0