State


V této části se podíváme na State. Jedná se o návrhový vzor, ve kterém je chování objektu určeno jeho stavem.

Proč State použít

Vezměmě v úvahu obyčejný telefon. To co s ním děláme závisí na jeho stavu a stavu telefonní linky. Pokud telefon zvoní nebo chceme zavolat, tak jej musíme vzít. Abychom mohli telefonovat, tak musí být telefon vytažen z držáku. Pokud někomu voláme a je zrovna obsazený, tak položíme sluchátko. Telefon tedy může být v různých stavech a podle toho máme jiné možnosti co s ním můžeme dělat. Návrhový vzor State se můžeme rozhodnout použít, když chceme aby nějaký objekt nabýval různých stavů.

V JavaScriptu si můžeme vzít jako příklad Promise. Může nabývat tří stavů: PENDING, REJECTED nebo FULFILLED.

Konstrukce, která řídí stavy a přechody mezi nimi se nazývá State Machine. Je výrazně jiná než návrhový vzor State. Existují knihovny, které můžeme použít a nemusíme si ji vytvářet sami. Příklad její tvorby zde není ukázán.

Příklad - Přepínač

Následující příklad ukazuje třídu Prepinac, reprezentující přepínač, který může nabývat dvou stavů. Může být vypnutý nebo zapnutý. Třída Prepinac obsahuje vlastnost state, která uchovává aktuální stav, ve kterém se přepínač právě nachází. Podle toho jestli je vypnutý nebo zapnutý, obsahuje tato vlastnost jiný typ State objektu.

// třída reprezentující přepínač
class Prepinac {
    constructor() {
        // state objekt určující stav přepínače
        this.state = new OffState();
    }

    // metoda pro zapnutí přepínače
    on() {
        // zavolání metody on state objektu
        this.state.on(this);
    }

    // metoda pro vypnutí přepínače
    off() {
        // zavolání metody off state objektu
        this.state.off(this);
    }
}

// základní třída pro State třídy
class State {
    constructor() {
        if (this.constructor === State)
            throw new Error('abstract!');
    }

    // v základní třídě se v metodě on vypíše,
    // že je přepínač již zapnutý
    on(prepinac) {
        console.log("Přepínač je již zapnutý.");
    }

    // v základní třídě se v metodě off vypíše,
    // že je přepínač již vypnutý
    off(prepinac) {
        console.log("Přepínač je již vypnutý.");
    }
}

// State pro zapnutý stav přepínače
class OnState extends State {
    constructor() {
        super();
        // při vytvoření OnStatu se vypíše, že je přepínač zapnutý
        console.log("Přepínač je zapnutý.");
    }

    // metoda off vypne přepínač - nastaví mu vlastnost
    // state na nový OffState
    off(prepinac) {
        console.log("Přepínač se vypíná...");
        prepinac.state = new OffState();
    }
}

// State pro vypnutý stav přepínače
class OffState extends State {
    constructor() {
        super();
        // při vytvoření OffStatu se vypíše, že je přepínač vypnutý
        console.log("Přepínač je vypnutý.");
    }

    // metoda on zapne přepínač - nastaví mu vlastnost
    // state na nový OnState
    on(prepinac) {
        console.log("Přepínač se zapíná...");
        prepinac.state = new OnState();
    }
}


const prepinac = new Prepinac();
prepinac.on();
prepinac.off();
prepinac.off();

Předchozí příklad ukazuje vytvoření přepínače pomocí návrhového vzoru State. Určitě není dobré k tak jednoduché věci State použít, ale dobře to ilustruje, jak tento návrhový vzor vlastně funguje.