2015-04-20 1 views
0

Я ищу элегантное решение для своего дела. Я попытался найти шаблон дизайна, который указал и предлагает решение для этого случая, но я не смог его найти.Должен вызывать первый шаблон дизайна

У меня есть базовый класс, который использует для хранения общего объекта, а затем вызывает его. Я хочу, выполнение будет разделен на две части:

  1. А должны иметь часть, которая всегда будет иметь место (do1st()).
  2. Пользовательский код (do2nd()).

Например:

class InvokeBase 
{ 
public: 
    InvokeBase(void *ptr) : context_(ptr) {} 
    virtual ~InvokeBase() {} 
    void operator()() = 0; 
protected: 
    void do1st() {//Mandatory code to execute for every InvokeBase type when calling operator()}; 
    void * context_; 
}; 

class InvokeDerived : public InvokeBase 
{ 
public: 
    InvokeDerived(void *ptr) : base(ptr){} 
    virtual ~InvokeDerived(); 
    void do2nd() {//User defined code} 
    void operator()() 
    { 
     do1st(); // << How to force this execution? 
     do2nd(); 
    } 
}; 

void main() 
{ 
    InvokeBase *t = new InvokeDerived(); 
    t(); // << here i want the execution order will be do1st and then do2nd. 
} 

Хитрость заключается в том, что я хочу do1st будет выполняться всегда, что я не должен вызывать его из InvokeDerived. Я хочу разрешить пользователю наследовать от InvokeBase с гарантией, что do1st всегда будет вызываться при вызове оператора().

+3

[Шаблон Метод шаблон] (HTTP: //en.wikipedia.org/wiki/Template_method_pattern) –

+0

'void * context' - это C-решение. В C++ у нас есть несколько лучших решений. В этом случае решением будет просто удалить «context», поскольку он не используется. Также непонятно, почему 'InvokeBase' будет содержать контекст, так как кажется более логичным хранить контекст в' InvokeDerived'. – MSalters

ответ

4

Это шаблон метод шаблона: разделить функции с полугибкого поведения accross классовой иерархии на несколько частей, и сделать виртуальные только те, которые изменяют:

class InvokeBase 
{ 
public: 
    InvokeBase(void *ptr) : context_(ptr) {} 
    virtual ~InvokeBase() {} 
    void operator()() // this is non-virtual (this is the template method) 
    { 
     do1st(); 
     do2nd(); // this resolves to virtual call 
    } 

protected: 
    void do1st() { /* fixed code here */ }; 
    virtual void do2nd() = 0; // variable part here 
    void * context_; 
}; 

class InvokeDerived : public InvokeBase 
{ 
public: 
    InvokeDerived(void *ptr) : base(ptr){} 
    virtual ~InvokeDerived() = default; 

protected: 
    void do2nd() override 
    { 
     // code speciffic to InvokeDerived here 
    } 
}; 
Смежные вопросы