当只能改变一侧时,重构紧密耦合的类

时间:2014-12-15 22:09:44

标签: c++ templates design-patterns

请提前为这个冗长的问题道歉。这是我能想到的最小的自包含示例...我很确定必须有一些明显的/漂亮/整洁的解决方案,但我目前无法看到它。

好的,这就是问题所在:想象一下以下情况(nb。代码的可编译版本可在http://goo.gl/dhRNex获得)。假设

struct Thing1 {
public:
  void bar(class Implementation1 &i) {
    i.baz();
  }

  // ...various other methods like bar()
};

struct Thing2 {
public:
  void bar(class Implementation2 &i) {
    i.qux();
  }

  // ...various other methods like bar()
};

给出。不幸的是,这些类是固定的,即不能改变/重构。

但是,Implementation1Implementation2是可更改的。这两个类共享很多类似的代码,因此将共享代码放在一个公共基类中似乎很自然。但是,代码依赖于Thing使用的类型,但Thing1Thing2没有共同的基类,因此使用模板似乎也很自然。因此,我想出了基类

的以下解决方案
template<class T, class S>
struct ImplementationBase {
public:
  S *self;

  void foo() {
    T thing;
    thing.bar(*self);
  }

  // ...lots more shared code like foo()
};

和具体实施

struct Implementation1 : public ImplementationBase<class Thing1, class Implementation1> {
public:
  Implementation1() {
    self = this;
  }

  void baz() {
    std::cout << "Qux!" << std::endl;
  }
};

struct Implementation2 : public ImplementationBase<class Thing2, class Implementation2> {
public:
  Implementation2() {
    self = this;
  }

  void qux() {
    std::cout << "Qux!" << std::endl;
  }
};

理想情况下,我会在this中使用self代替foo,但问题是this的类型为ImplementationBase<class Thing1, class Implementation1>,但{{1} }} 是必须的。显然,整个过程非常混乱,Implementation1Implementation类太紧密耦合了,但是如果不能重构Thing类,我就看不出简单的出路。所以,最后,我的问题是:

  1. 使用上面的Thing技巧是否有更好的选择?
  2. 是否有设计可以更好地解决这个问题? (我有一种感觉,有,但我错过了一些明显的东西)
  3. 如果你已经做到这一点,非常感谢花时间阅读整个故事,并为这个冗长的问题再次道歉。

1 个答案:

答案 0 :(得分:2)

您已经在使用CRTP,因此您根本不需要自己:

template<class T, class S>
struct ImplementationBase {        
public:
  S* getThis() { return static_cast<S*>(this); }

  void foo() {
    T thing;
    thing.bar(*getThis());
  }

  // ...lots more shared code like foo()
};