我正在使用基於Eclipse(和其他的)擴展點模型的動態加載共享庫的插件框架。所有插件共享類似的屬性(名稱,ID,版本等),每個插件理論上可以滿足任何擴展點。實際的插件(即Dll)處理由另一個庫管理,我所做的只是管理應用程序接口的集合。避免枚舉作爲接口標識符c + + OOP
我開始使用enum PluginType
來區分不同的接口,但我很快意識到,使用模板函數使得代碼更加清晰,並且將繁重的工作留給編譯器,而不是迫使我使用大量的聲明。
唯一的問題是我需要爲類成員指定類似的功能 - 最明顯的例子是提供特定接口的默認插件。一個Settings
類處理所有設置,包括接口的默認插件。
即Skin newSkin = settings.GetDefault<ISkin>();
如何存放在容器中的默認ISkin
而不訴諸識別接口的一些其他手段?
正如我上面提到的,我當前使用std::map<PluginType, IPlugin> Settings::defaults
構件來實現這一(其中IPlugin
是一個抽象基類,所有的插件從派生。然後我可以dynamic_cast
到所需的接口需要時,但是這確實味道不好設計的我和介紹弊大於利我覺得
歡迎任何提示
編輯:這裏是當前使用的默認插件的例子
typedef boost::shared_ptr<ISkin> Skin;
typedef boost::shared_ptr<IPlugin> Plugin;
enum PluginType
{
skin,
...,
...
}
class Settings
{
public:
void SetDefault(const PluginType type, boost::shared_ptr<IPlugin> plugin) {
m_default[type] = plugin;
}
boost::shared_ptr<IPlugin> GetDefault(const PluginType type) {
return m_default[type];
}
private:
std::map<PluginType, boost::shared_ptr<IPlugin> m_default;
};
SkinManager::Initialize()
{
Plugin thedefault = g_settings.GetDefault(skinplugin);
Skin defaultskin = boost::dynamic_pointer_cast<ISkin>(theskin);
defaultskin->Initialize();
}
我寧願調用getdefault,如下所示,並自動轉換爲派生類。不過,我需要專門爲每個類的類型。
template<>
Skin Settings::GetDefault<ISkin>()
{
return boost::dynamic_pointer_cast<ISkin>(m_default(skin));
}
你可以發表一些示例代碼來說明如何使用默認值?我很難想象你在說什麼。 – 2010-03-25 13:41:09
如果'IPlugin'是一個抽象類,則需要在地圖中存儲指針(無論如何您都需要這樣做,否則就會出現切片問題)。 – 2010-03-25 13:43:48
嗨克里斯托,增加了更多的例子 – AlasdairC 2010-03-25 14:00:05