所以我有一个正在编写的基于插件的系统。用户可以创建一个Plugin类的子类,然后在运行时将其加载并与系统的其余部分集成。从系统运行插件时,它在一组插件的上下文中运行,我称之为会话。

我的问题是,在用户插件中,可以使用两个名为pf_ostream和pf_istream的流类来向系统读取/写入数据。我想以某种方式将插件实例的会话变量绑定到pf_ostream和pf_istream,以便用户实例化这些类时,它们已经为他们绑定了会话(基本上我不希望他们看到会话内部)

我可以使用宏完成此操作,将对构造函数的调用包装为:

#define MAKE_OSTREAM = pf_ostream_int(this->session)


但是我认为可能会有更好的方法。我看着在包装pf_ostream的Plugin中使用嵌套类,但是看起来嵌套类无法以一种封闭的方式访问封闭的类变量。

有人知道这样做的巧妙方法吗?

最佳答案

这是基于您在评论中提到的工厂想法的另一个答案。它使用Facade模式在绑定到SystemSession类中集中创建系统设施:

#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类)中。如果System类在使用了更多或更少系统设施的另一个应用程序中重复使用,则可能需要更改。

编辑:

这是如何应用Proxy模式(以及Pimpl惯用语)以获取具有值语义的引用计数流类的方法:

#include <boost/shared_ptr.hpp>

class pf_ostream
{
public:
    pf_ostream(Session* session);
    pf_ostream& operator<<(int rhs);
    // Use of default copy-constuctor and assignment operator
    //    will work fine because of shared_ptr.

private:
    struct Impl;
    boost::shared_ptr<Impl> pimpl_;
};

// In cpp file

struct pf_ostream::Impl
{
    Impl(Session* session) : session(session) {}
    void insert(int rhs) {/*...*/}
    Session* session;
};

pf_ostream::pf_ostream(Session* session) : pimpl_(new Impl(session)) {}

pf_ostream& pf_ostream::operator<<(int rhs) {pimpl_.insert(rhs); return *this;}


用户将必须意识到代理对象的副本将引用相同的实际流。希望这可以帮助。

10-06 05:05
查看更多