什么是实施半虚拟'的最佳做法?方法?

时间:2016-05-29 23:52:19

标签: c++ design-patterns

我知道不可能存在半虚拟的'但是,我遇到了与设计相关的问题。

我们说我有一个名为WebPage的基类。该类有一个名为UpdatePage()的方法。但是因为此方法存在于抽象WebPage对象中,所以UpdatePage()方法是虚拟的,并且应该由从WebPage派生具体类的用户实现。

但是,让我们说当调用UpdatePage()方法时,理想的是它会为某个类数据成员设置关于上次更新时间的时间戳。

我想从一个方法(即做一个时间戳)中想要一些默认实现,但我也希望实现是从基类WebPage派生的具体类中自定义的。

我知道我可以拿出一些技巧来解决这个问题。例如,我可以使UpdatePage()非虚拟,并使其包含两个方法:非虚拟的timeStamp()方法和纯虚拟的updateImplementation()方法。这样,当用户调用UpdatePage()时,将存在默认和自定义行为。

但同样,如果存在一些设计模式/规则,我不想重新发明轮子。

谢谢!

1 个答案:

答案 0 :(得分:3)

您在问题中提到的是Template Method模式,它适合解决您的问题。

简而言之,您的UpdatePage()将提供一个"模板" of flow,让派生类提供模板的缺失部分:

class WebPage {
public:
    virtual UpdatePage() {  // optional for the virtual
        // Update the timestamp

        // Call the logic provided by derived class
        DoUpdatePage();

        // Some other logic afterwards if you need
    };

protected:
    virtual DoUpdatePage() = 0;  // you may also provide a default impl too
};

(希望语法正确,已经有一段时间没有触及C ++了。但是这个想法应该很清楚了)

另一种可能的模式,取决于你的设计,是装饰师。

简而言之,不是直接使用派生类,而是通过提供时间戳逻辑的装饰器来装饰它

e.g。

class WebPage {
public:
    virtual void UpdatePage() = 0;
};

class TimeStampWebPageDecorator : public WebPage {
public:
    TimeStampWebPageDecorator(WebPage* webpage) : impl(webpage) {
    }

    virtual void UpdatePage() {
        // logic for the timestamp stuff

        impl->UpdatePage();

        // some other logic after calling impl
    }

private:
    WebPage * impl;
}

因此,如果您要调用WebPage impl,则可以使用TimeStampWebPageDecorator进行装饰。 E.g。

FooWebPage fooWebPage{};

// Instead of invoking fooWebPage directly like this.
// WebPage& webpage = fooWebPage;
// webpage.UpdatePage()

// Decorate it first
WebPage& webpage = TimeStampWebPageDecorator{&fooWebPage};
webpage.UpdatePage()