包含“实现”和“接口”指针的C ++类有什么用?

时间:2010-03-03 07:28:38

标签: c++ design-patterns class-design

我正在研究一些源代码,我只是想知道为什么一个类(或类)经常以这种方式实现:


class EventHandler
{
...
    EventDispatcher* m_Dispatcher;
    virtual bool ProcEvent( EventHandler* Sender, int Task, int Event, void* Param );
...
};

class ClassA: public EventHandler
{
...
    ClassA* m_Impl;
    ClassA* m_Iface;
...
public:
    // virtual functions
    virtual bool ProcEvent( EventHandler* Sender, int Task, int Event, void* Param );
    virtual void OnDataWritten(const PIOResult&) {;}
    ...

    // sample functions
    void SetImplement( ClassA* aImpl );
    void SetInterface( ClassA* aIface );
    ClassA* GetImplement() { return m_Impl; }
    ClassA* GetInterface() { return m_Iface; }
    bool GetData( list& aList );
};

// Implementation of some sample functions; Most of its function contain more
// or less the same format as below, with the return m_Impl->XXX having the same
// name as the function being defined (e.g. A::XXX)
bool ClassA::GetData( list< Data >& aList )
{
    if( m_Impl )
        return m_Impl->GetData( aList );
    else
        return false;
}

class ClassAFactory: public EventHandler
{
private:
    ClassAFactory* m_Impl;
    ClassAFactory* m_Iface;

protected:
    virtual ClassA* MakeTransport();

    virtual bool ProcEvent( EventHandler* Sender, int Task, int Event, void* Param );
    virtual ClassA* CreateClassA() { return 0; }

...
};

// In some member function of ClassB (ClassB inherits ClassA)

switch( status )
{
    case 1:
        GetInterface()->OnDataWritten();
    case 2:
        // ...
};


我相信这是一些设计模式,但我不熟悉它。如果我知道它是什么,它可以帮助我理解。任何人都可以帮我指出它可能是什么或这些类的使用是什么,以便以这种方式实现?

我认为这是一些事件处理和一些工厂一起使用但我不确定。

4 个答案:

答案 0 :(得分:2)

我猜测,但它可能是你正在寻找的“pimpl成语”吗? http://www.gamedev.net/reference/articles/article1794.asp

修改
带有GetData实现的扩展代码示例绝对是pimpl习语的一个例子。但是,这并不能解释m_Iface成员。你能提供一个使用它的地方的例子吗?

EDIT2
通过添加如何显示m_Iface的示例,很清楚我对pimpl的看法是错误的。它是一种装饰者。 m_Impl指向底层对象,而m_Iface指向最外层,因此底层对象可以进行遍历整个装饰器链的调用。这个例子有点复杂,因为ClassA都是接口类和默认实现。如果您想为类创建装饰器,则必须继承ClassA。

答案 1 :(得分:2)

我担心使用的名称不具有usual含义,所以如果没有使用的内容或如何使用它们的例子,那就很难猜测。

你应该检查两种设计模式,大量使用这种self-recursion(在班级*):

我担心你正在寻找那些无法模仿其中任何一种的东西。

Decorator中,重点是添加功能。为此,您有Interface个派生Concrete类和Wrapper接口。然后各种包装器将派生Wrapper,你可以链接它们:

Interface* interface = new Wrapper2( new Wrapper1 ( new Concrete() ) );

每个包装器都添加了一些功能,而这里我们只有完美的转发...所以它不是Decorator

Composite模式不同。它的目标是隐藏您是否使用元素集合或单个元素处理。通常的示例是树:如果使用Composite模式实现操作,则可以将操作应用于整个子树或仅应用叶节点。

再一次,这里没有这样的东西。

所以我最好的猜测是你有一个疯狂的设计(可能是一个误导的模仿一个众所周知的模式的尝试),或者你没有给我们足够的信息(源代码)来找出这个角色。无论如何,这似乎很奇怪。

*注意:在类级self-recursion我的意思是类A的对象指向类A的另一个对象,但这并不意味着(当然)它指向它对同一个实例...否则我们会有一个Stack Overflow(双关语)。在SetImplementation调用期间,这个不是同一个实例位肯定值得检查:请注意,任何循环引用都会因递归而导致死亡。

答案 2 :(得分:0)

这看起来比C ++更多。在任何面向对象的语言中,您都可以使用继承和虚函数来获得此行为。

使用指向实现类的内部指针非常好(pimpl习惯用法),但调用者通常无法访问此指针。而且我根本没有获得接口指针。

答案 3 :(得分:0)

我不确定这是否是pimpl成语的经典示例,但如果是这样,那么重点是将接口(应该是稳定的)与实现细节分开(这应该是相对的)可以自由改变。