所以我有一个基于插件的系统,我正在编写。用户可以创建Plugin类的子类,然后在运行时加载它并与系统的其余部分集成。当从系统运行插件时,它在一组插件的上下文中运行,我称之为Session。
我的问题是在用户插件中,有两个名为pf_ostream和pf_istream的流类可用于向系统读/写数据。我想以某种方式将插件实例的会话变量绑定到pf_ostream和pf_istream,以便当用户实例化这些类时,它已经绑定到它们的会话(基本上我不希望它们看到会话内部)
我可以用宏执行此操作,包含对构造函数的调用,如:
#define MAKE_OSTREAM = pf_ostream_int(this->session)
但我认为可能有更好的方法。我看了在Plugin包装pf_ostream中使用嵌套类,但看起来嵌套类不能以闭包方式访问封闭类变量。
有没有人知道这样做的好方法?
答案 0 :(得分:1)
这是基于您在其中一条评论中提到的工厂理念的另一个答案。它使用Facade模式将系统工具的创建集中在绑定到System
的{{1}}类中:
Session
如果您有许多系统工具,则应明智地使用前向声明以避免长编译时间。此解决方案的缺点是将系统设施集中在依赖关系“焦点”(#include <boost/shared_ptr.hpp>
class System
{
public:
typedef boost::shared_ptr<pf_ostream> pf_ostream_ptr;
typedef boost::shared_ptr<pf_istream> pf_istream_ptr;
// Other system facilities...
System(Session* session) : session_(session) {}
pf_ostream_ptr makeOstream()
{return pf_ostream_ptr(new pf_ostream(session_));}
pf_istream_ptr makeIstream()
{return pf_istream_ptr(new pf_istream(session_));}
private:
Session* session_;
};
class Plugin
{
public:
Plugin(System* system) : system_(system) {}
System& system() {return *system_;}
private:
System* system_;
};
class MyPlugin : public Plugin
{
public:
MyPlugin(System* system) : Plugin(system) {}
void print()
{
pf_ostream_ptr pfos( system().makeOstream() );
*pfos << "Hello World!\n";
// pfos will be deleted automatically at the end of this scope
}
};
类)中。如果System
类在另一个使用更多或更少系统工具的应用程序中重用,则可能需要更改它。
修改强>
以下是如何应用代理模式(以及Pimpl习惯用法)来获取具有值语义的引用计数流类:
System
用户必须知道代理对象的副本将引用相同的实际流。希望这会有所帮助。
答案 1 :(得分:0)
您可以在构造过程中为嵌套类提供对其父类的引用。
class plugin_base {
protected:
plugin_base(): _istream(*this) {}
class istream {
public:
istream(plugin_base& p): _plugin(p) {}
...
private:
plugin_base& _plugin;
};
istream _istream;
};
class plugin: public plugin_base {
...
};
每次实例化它的子类时,编译器都会自动调用plugin_base的构造函数。
答案 2 :(得分:0)
可以使用具有Session的事物的接口类。这里有一些值得深思的东西:
class IContext
{
public:
virtual ~IContext() {}
virtual Session* session() = 0;
};
class Plugin : public IContext
{
public:
Plugin(Session* session) : session_(session) {}
virtual ~Plugin() {}
virtual Session* session() {return session_;}
protected:
Session* session_;
};
class MyPlugin : public Plugin
{
public:
MyPlugin(Session* session) : Plugin(session) {}
virtual ~MyPlugin() {}
void print()
{
pf_ostream pfos(this);
pfos << "Hello world!\n";
}
};
class pf_ostream
{
public:
pf_ostream(IContext* context) : session_(context->session()) {}
// ...
private:
Session* session_;
// ...
};
请注意插件编写者现在如何使用pf_ostream pfos(this)
代替pf_ostream pfos(this->session)
,现在忘记了Session
。 pf_ostream
也忽略了Plugin
及其后代。
IContext可能不是这里最好的名字。也许IHasSession? (IHasCheezburger ???)