niedziela, 14 listopada 2010

State Pattern

State Pattern - zgodnie z definicją: pozwala na zmianę zachowania obiektu przez zmianę jego stanu wewnętrznego.

Spójrzmy na diagram:

Context - klasa, która może posiadać różne stany
State - definiuje wspólny interfejs dla wszystkich stanów, dzięki temu są wymienne.
ConcreteState - definiuje konkretną definicję stanu.

Działanie wzorca jest bardzo proste. Wywołując metodę Handle(), wykorzystywana jest odpowiednia implementacja stanu.

Patrząc na powyższy diagram, można odnieść wrażenie, że definicja wzorca jest praktycznie taka sama jak w przypadku wzorca Strategy. Jest jednak mała różnica między tymi dwoma wzorcami:
State Pattern:
- zbiór zachować opakowanych klasami
- w danym momencie klasa odnosi się do jednego z tych stanów
- klient nie zna aktualnego (lub bardzo mało wie) stanu obiektu - nie definiuje go jawnie
Strategy Pattern:
- klient sam definiuje obiekt strategi który jest wykorzystywany w operacji

Możemy także podejść do tego od innej strony:
Mówiąc Strategy Pattern myślmy o zastępstwie dla dziedziczenia.
Mówiąc State Pattern myślmy o instrukcji if/switch w naszej klasie i wielu sprawdzanych warunkach.

Na koniec oczywiście przykład wykorzystania wzorca:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public interface CocaColaMachineState
    {
        void GetCookCan();
    }

    public class ReadyState : CocaColaMachineState
    {
        public CocaColaMachine cocaColaMachine;
        public ReadyState(CocaColaMachine cocaColaMachine)
        {
            this.cocaColaMachine = cocaColaMachine;
        }

        public void GetCookCan()
        {
            Console.WriteLine("Have a good day!");
            cocaColaMachine.canCount -= 1;
            if (cocaColaMachine.canCount <= 0)
            {
                cocaColaMachine.state = cocaColaMachine.emptyState;
            }
        }
    }

    public class EmptyState : CocaColaMachineState
    {
        public CocaColaMachine cocaColaMachine;
        public EmptyState(CocaColaMachine cocaColaMachine)
        {
            this.cocaColaMachine = cocaColaMachine;
        }

        public void GetCookCan()
        {
            Console.WriteLine("The Machine is Empty. Sory :(");
        }
    }

    public class CocaColaMachine
    {
        public ReadyState readyState { get; private set; }
        public EmptyState emptyState { get; private set; }
        public CocaColaMachineState state { get; set; }
        public int canCount { get; set; }

        public CocaColaMachine(int canCount)
        {
            readyState = new ReadyState(this);
            emptyState = new EmptyState(this);

            this.canCount = canCount;
            if (canCount > 0)
            {
                state = readyState;
            }
            else
            {
                state = emptyState;
            }
        }

        public void GetCookCan()
        {
            state.GetCookCan();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            CocaColaMachine cocaColaMachine = new CocaColaMachine(4);
            cocaColaMachine.GetCookCan();
            cocaColaMachine.GetCookCan();
            cocaColaMachine.GetCookCan();
            cocaColaMachine.GetCookCan();
            cocaColaMachine.GetCookCan();
        }
    }
}

Brak komentarzy:

Prześlij komentarz