2009-12-15 4 views
0

Я ищу лучший способ отправки объектов в правильный «целевой» объект.Какой шаблон дизайна/RTTI

У меня есть базовый командный класс: Cmd, два подкласса: BufferCmd и StateCmd. Команда «GotoLine» выводится из BufferCmd, а «ChangeCmd» - из StateCmd. BufferCmds предназначены для перехода к классу Buffer, а StateCmds предназначены для перехода к объекту State.

Я в настоящее время паттерн посетитель настроен так, что я могу сделать что-то вроде:

Buffer buffer; 
State state; 

Cmd *c; 
GotoLineCmd gotoCmd = new GotoLineCmd (15); 
ChangeCmd changeCmd = new ChangeCommand (...) 

c = &gotoCmd; 
c->accept (buffer); 
c = &changeCmd; 
c->accept (state); 

Я хочу использовать шаблон Visitor, потому что я хотел бы быть в состоянии сделать что-то примерно так:

Cmd *cmds [5]; 
cmds [0] = new GotoLineCmd (...); 
cmds [1] = new CopyLineCmd (...); 
cmds [2] = new PasteCmd (...); 

foreach (Cmd *c in cmds) { 
    c->accept (buffer); 
} 

К сожалению, для этого мне нужно знать, к какому объекту отправить команду. Я хотел бы иметь возможность сделать что-то вроде этого:

Derive Buffer from Commandable 
Derive State from Commandable 

Commandables *commandables [1] = {new Buffer(), new State() }; 

// Then have the foreach type statement look like: 
foreach (Cmd *c in cmds) { 
    c->accept (commandables); 
} 

Есть ли образец, наиболее подходящий для такого рода ситуаций? Должен ли я использовать шаблон посетителя? Очевидные Я хочу, чтобы избежать этого:

foreach (Cmd *c in cmds) { 
    foreach (Commandable *cmdAbles in commandables) { 
     if (c->accept (commandables)) { 
       // Okay command accepted... 
       break; 
     } 
    } 
} 

Благодаря

ответ

3

звучит, как вы хотите, метко названный Command pattern.

Ключ должен переместить различные параметры accept() в конструктор каждого класса, полученный из Cmd. Например, конструктор GotoLineCommand возьмет линию и объекты буфера в качестве параметров для своего конструктора и сохранит указатель или ссылку на объект буфера.

После того, как вы сделали это, вы больше не нужны параметры accept() и интерфейс одинаков во всех классах, полученных из Cmd

class Buffer 
{ 
    public: 
     void gotoLine(int line); 
}; 

class Cmd 
{ 
    public: 
     virtual void accept() = 0; 
}; 

class GotoLineCommand: public Cmd 
{ 
    public: 
     GotoLineCommand(Buffer & buffer, int line) : 
     buffer_(buffer), 
     line_(line) 
     { 
     } 

     virtual void accept() 
     { 
     buffer_.gotoLine(line_); 
     } 

    private: 
     Buffer & buffer_; 
     int line_; 
}; 
Смежные вопросы