Реализация управляемых государством классов - PullRequest
1 голос
/ 29 декабря 2008

Предположим требование реализации класса «CAR».

Теперь этот класс содержит различные состояния, такие как "не зажженный", "зажженный", "сломанный", "проколотый" и т. Д.,

Способ реализации этого требования, который я рассматриваю, заключается в том, чтобы иметь логические флаги, называемые «свойствами» в классе, и «проверять состояние», используя эти логические флаги внутри каждой функции-члена. Например,

CAR.goRacing() 
{
    if(bIsPunctured)
       return ENUM_CANT_DRIVE;

    //Start the Engine... 
}

Эта реализация, тривиальная, чтобы она выглядела, начинает становиться очень сложной, когда увеличивается число состояний, которые предоставляет объект. Я также видел случаи, когда одно состояние делает обслуживание объекта очень громоздким (я уверен, что в этом случае я виноват в моих навыках программирования)
Существует ли стандартный способ реализации такого управляемого государством объекта?

Я видел паттерн свойства Стива Йеггея , но я действительно не смог найти пример из реального мира!

Спасибо.

Ответы [ 2 ]

3 голосов
/ 29 декабря 2008

Это определенно звучит как работа для State Pattern

По сути, вы создаете свое приложение (контекст) и определяете поведение для какой-либо операции в отдельный класс / интерфейс (состояние)

Этот класс будет иметь различные подклассы реализации, по одному на состояние.

Когда состояние изменяется, объект состояния назначает новое состояние контексту. Таким образом, вы получаете весь код штата в отдельные классы и избегаете классического кода спагетти.

EDIT

Вот самая простая реализация, о которой я мог подумать.

Предположим, у вас есть "домашнее животное". Паштет делает что-то в соответствии с состоянием, в которое он входит.

Когда это состояние завершено, состояние меняется на следующее (состояние сна -> разбудить -> играть и т. Д.)

Я даже не знаю, компилируется ли это. Это только чтобы понять идею *

//These are the states of the "Pet" class
//sleep -> wake up ->  play -> dinner -> sleep -> wake up .. etc. 
class Pet {

    State currentState;
    static Pet createNew(){
        Pet p = new Pet();
        State s = new Sleep();
        s.setContext( p );
        p.currentState = 
        return p;
    }

    public void doSomething(){ 
        currentState.doSomething();
   }

}   

abstract class State {
    Pet context;
    void setContext( Pet c ) { 
        this.context = c;
    }
    abstract doSomething();
    void sout( Striing message ) { 
        System.out.println( message );
    }
}
class Sleep extends State { 
    public void doSomething(){
       sout( "zzzZZZ ... " );
       State nextState = new WakeUp();
       nextState.setContext( context );
       context.currentState = nextState;
    }
}
class WakeUp extends State { 
    public void doSomething(){
       sout( "uuuaaaaww... zzzz What time is it? ... " );
       State nextState = new Play();
       nextState.setContext( context );
       context.currentState = nextState;
    }
}
class Play extends State { 
    public void doSomething(){
       sout( "boing, boing, poing, poing" );
       State nextState = new Dinner();
       nextState.setContext( context );
       context.currentState = nextState;
    }
}
class Dinner extends State { 
    public void doSomething(){
       sout( "Yum, yum..." );
       State nextState = new Sleep();
       nextState.setContext( context );
       context.currentState = nextState;
    }

}

И тогда ваш клиентский класс просто использует его!

Pet myPet = Pet.createNew();

while( I_FeelLikePlaying() ){ 
    myPet.doSomething();
}
0 голосов
/ 29 декабря 2008

См. здесь для улучшенной версии шаблона состояния с использованием преимуществ .NET-средств. Состояние может быть простой функцией (которая будет выполнять большую часть времени), но также может быть объектом (или другим конечным автоматом) ...

С уважением,

Andreas

...