类与不同所有者的兼容性

时间:2011-03-28 08:35:14

标签: c++ design-patterns

鉴于

class Foo1 { 
 public:
  typedef Foo2 owner;
};
class Foo2 {
 public:
  typedef Foo1 vassal;
  typedef Foo3 owner;
};
//... and so on 
class FooN {
 public:
  typedef FooNm1 vassal;
  typedef ExternalType owner;  // problem
  owner* owner();
};

问题:

如何将类层次结构与外部所有者相关联,从而保持不同所有者的类之间的兼容性。

问题

  1. 如果我们使用所有者作为模板参数使FooN成为模板,那么Foo {N}层次结构的每个类都将被该所有者通过依赖链感染。
  2. 如果我们为外部所有者创建一个接口FooNOwner来继承,那么我们需要动态转换才能从Foo {N}层次结构上的算法转移到实际所有者。
  3. 是否有解决我问题的设计模式?

    出现这些问题的情况示例: 您有一个由Foo {N}类组成的结构。它用于快速搜索,并从中返回查询返回Foo {N}对象的列表。我想从返回的FooN对象中获取具有外部所有者的具体类型ExternalOwner *的指针,因此避免动态转换。与此同时,我希望使用Foo {N}(可能没有FooN)对象与不同的FooN :: owner进行操作,而不回顾这种差异。

    更新

    执行此操作的唯一有效方法可能是定义公共所有者接口并由所有者重载它以在不同所有者类发生的上下文中使用。因此,该接口由其使用的上下文定义(但是FooN与FooN :: owner使用的上下文无关)。这是我最初试图解决的问题 - 分开不同的任务,这种方法对我没有帮助。

    我的解决方案

    我结束了双重调度。如果我添加虚拟void apply(FooOwnerVisitor *)= 0;函数到FooOwner并在附近定义FooOwnerVisitor接口,然后我可以为FooOwner衍生物添加任何功能,而不会影响FooN层次结构和没有dynamic_cast。

2 个答案:

答案 0 :(得分:0)

我认为没有人清楚你的要求,但这是我最好的解决方法......说明如何在模板解决方案中处理你所谓的“依赖链”。如果这没有帮助,但有任何相关性,那么解释它和问题将有助于人们帮助你。如果你想在Foo<>个对象上应用算法循环,我可以说明如何做到这一点......

#include <iostream>

struct Abstract_Bar
{
    virtual void f() const = 0;
};

struct Bar1 : Abstract_Bar
{
    void f() const { std::cout << "Bar1\n"; }
};

struct Bar2 : Abstract_Bar
{
    void f() const { std::cout << "Bar2\n"; }
};

template <int N>
struct Foo
{
    typedef Foo<N - 1> Lower;
    typedef Foo<N + 1> Higher;

    void f() const { std::cout << "Foo<N>\n"; }

    Higher* higher_;
};

template <>
struct Foo<1>
{
    typedef Foo<2> Higher;

    void f() const { std::cout << "Foo<1>\n"; }

    Higher* higher_;
};

template <>
struct Foo<4>
{
    typedef Foo<3> Lower;
    typedef Abstract_Bar Higher;

    void f() const { std::cout << "Foo<4>\n"; }

    Higher* higher_;
};

int main()
{
    Foo<1> foo1;
    Foo<2> foo2;
    Foo<3> foo3;
    Foo<4> foo4;
    foo1.higher_ = &foo2;
    foo2.higher_ = &foo3;
    foo3.higher_ = &foo4;
    Bar1 bar1;
    foo4.higher_ = &bar1;

    foo1.f();
    foo2.f();
    foo3.f();
    foo4.f();

    foo1.higher_->f();
    foo2.higher_->f();
    foo3.higher_->f();
    foo4.higher_->f();

    // switch to another type of "Bar"...
    Bar2 bar2;
    foo4.higher_ = &bar2;
    foo4.higher_->f();
}

答案 1 :(得分:0)

我结束了双重调度。如果我添加虚拟void apply(FooOwnerVisitor *)= 0;函数到FooOwner并在附近定义FooOwnerVisitor接口,然后我可以为FooOwner衍生物添加任何功能,而不会影响FooN层次结构和没有dynamic_cast。所以我的问题实际上有两个问题,有自己的解决方案。首先 - 如何使来自不同所有者的FooN类兼容 - 从所有者接口继承。第二 - 如何避免动态转换FooNOwner派生类 - 使用访问者模式。必须考虑将问题分成较小的问题并结合原子解决方案。