C++ 执行类型转换的中介模板
我正在评估观察者模式的实现策略,其中一个要求是基本C++ 执行类型转换的中介模板,c++,templates,observer-pattern,C++,Templates,Observer Pattern,我正在评估观察者模式的实现策略,其中一个要求是基本主题类在事件类的派生(具体)类中实现方法 在原型实现中,我在具体事件类中获得了以下代码: // a concrete event class evZoom : public AbstractEvent { public: virtual void Fill( Subject *aZoomManager) { mRatio = dynamic_cast<ZoomManager *>(aZoomManage
主题
类在事件
类的派生(具体)类中实现方法
在原型实现中,我在具体事件类中获得了以下代码:
// a concrete event
class evZoom : public AbstractEvent
{
public:
virtual void Fill( Subject *aZoomManager)
{
mRatio = dynamic_cast<ZoomManager *>(aZoomManager)->mRatio;
}
int mRatio;
};
//一个具体的事件
类evZoom:公共抽象事件
{
公众:
虚拟空白填充(主题*AzoManager)
{
mRatio=动态施法(AzoManager)->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;
}
//十二月
班级科目;
//主题类要使用的非模板抽象基类。
类抽象事件
{
公众:
虚拟空白填充(主题*AsObject)=0;
};
//执行类型转换的中介类
模板
类事件:公共抽象事件
{
公众:
//这是我们进行类型转换的地方。
虚拟空白填充(主题*对象)
{
tsObject*IsSubject=动态投影(AsObject);
//不知何故,编译器知道调用下面的抽象方法,但是如果
//我们改变它的名字,我们会得到一个无限循环-古怪。
填充(主体);
}
//一种新的抽象方法,通过具体事件来实现。
虚拟空洞填充(tsObject*AsObject)=0;
};
//主题基类
班级科目
{
公众:
//虚拟析构函数使该类具有多态性
//因此,我们可以动态地强制转换它。
虚拟~Subject(){}
作废订阅(AbstractEvent*aEvent)
{
aEvent->Fill(此);
}
};
//一门具体的学科课。
类ZoomManager:公共虚拟主题
{
公众:
国际货币基金组织;
};
//具体事件
类evZoom:公共事件
{
公众:
虚拟空白填充(ZoomManager*AzoManager)
{
mRatio=azommanager->mRatio;
}
国际货币基金组织;
};
int main(int argc,const char*argv[]
{
ZoomManager iZoomManager;
evZoom*iEvent=新的evZoom();
iZoomManager.Subscribe(iEvent);
返回0;
}
唯一的问题是,我直觉认为有更好的解决方案;主要是因为我不记得在任何源代码或库中见过像上面这样的中介类,但可能是我的经验不足
有人能为上述问题提供更好的解决方案吗?是否
ZoomManager
是您在Fill()
上期望的唯一类型?为什么不更改方法的签名?不-可能有很多具体的主题:ZoomManager、ScrollManager、Composite等。您是否只是尝试切换所有可能的类型?如果是这样,就需要双重分派dynamic_cast
通常是个坏主意。我不确定你所说的“切换所有可能的类型”到底是什么意思,但有大量的具体主题,因为这是框架的一部分,使用它的应用程序可能会增加数百个——框架本身都不知道。这会排除双重分派吗?我的意思是,在Fill
上,您似乎每次都希望看到一个ZoomManager
,或者您有一个开关(每个开关都有一个案例)来决定如何处理其他具体类型。