我知道不可能存在半虚拟的'但是,我遇到了与设计相关的问题。
我们说我有一个名为WebPage的基类。该类有一个名为UpdatePage()的方法。但是因为此方法存在于抽象WebPage对象中,所以UpdatePage()方法是虚拟的,并且应该由从WebPage派生具体类的用户实现。
但是,让我们说当调用UpdatePage()方法时,理想的是它会为某个类数据成员设置关于上次更新时间的时间戳。
我想从一个方法(即做一个时间戳)中想要一些默认实现,但我也希望实现是从基类WebPage派生的具体类中自定义的。
我知道我可以拿出一些技巧来解决这个问题。例如,我可以使UpdatePage()非虚拟,并使其包含两个方法:非虚拟的timeStamp()方法和纯虚拟的updateImplementation()方法。这样,当用户调用UpdatePage()时,将存在默认和自定义行为。
但同样,如果存在一些设计模式/规则,我不想重新发明轮子。
谢谢!
答案 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()