SW Design Pattern

Communità di raccolta di applicazioni di SW object oriented design pattern

 

AREA PERSONALE

 

TAG

 

ARCHIVIO MESSAGGI

 
 << Luglio 2024 >> 
 
LuMaMeGiVeSaDo
 
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
 
 

FACEBOOK

 
 

 

Perchè utilizzare il pattern state

Post n°3 pubblicato il 28 Gennaio 2010 da MatteoDegliEsposti

La domanda che sorge ad uno sviluppatore è perchè dovrei usare questo pattern. Per prima cosa voglio chiarire che l'utilizzo del pattern è tanto più efficace quando più la macchina a stati è grande e complicata.

Normalmente le macchine a stati sono implementate con un enumerativo ed uno switch che si perde a vista d'occhio. La crescita del numero di stati incide direttamente sulla manutenibilità del software.

Con il pattern state è possibile dividere in più file la macchina a stati, avendo una classe per stato . E' inoltre possibile sulle varie classi suddividere i campi privati che servono senza doverli tutti dichiarare in testa al programma. Se alcuni campi servono a più di uno stato si può opportunamente usare la classe Context o sottosezioni di essa. 

Da un punto di vista computazionale con il pattern state è potenzialmente possibile caricare uno stato solo al momento della transizione in esso. Ammetto che questa è una situazione molto al limite ma del tutto possibile.

Invito ad utilizzare il pattern provando ad aggiungere uno stato nuovo alla macchina a stati. Apprezzerete senza dubbi la pulizia e i tempi dell'operazione

 
 
 

Pattern state in practice

Post n°2 pubblicato il 25 Gennaio 2010 da MatteoDegliEsposti
 
Foto di MatteoDegliEsposti

La storia dei design pattern inizia nel 1994 con la pubblicazione del libro Design Patterns: Elements of Reusable Object-Oriented Software.

I 4 autori Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (The gang of four) possono essere considerati dei mostri sacri nella progettazione object oriented.

I design pattern rappresentano le risposte alle principali esigenze di programmazione in un ambiente Object Oriented. In pratica rappresentano le risposte ad alcune problematiche tipiche che si incontrano nelle progettazione di qualsiasi tipo di applicazione.

In questo primo articolo riporto un Patter molto semplice denominato State. Nella programmazione orientata agli oggetti, lo State è un design pattern comportamentale. Esso consente ad un oggetto di cambiare il proprio comportamento a run-time in funzione dello stato in cui si trova.

In questo articolo utilizzo il pattern per modellare una macchina a stati. L'impiego di macchine a stati è comune nel mondo dell'automazione per il controllo di passi di lavorazione che trasformano un insieme di materiali in un prodotto finito.

Ci sono diversi elementi che agiscono per modellare una macchina a stati. C'è un contesto di esecuzione, uno stato corrente e degli atri stati raggiungibili. Infine degli eventi che comportano delle transizioni da uno stato verso un altro. Il pattern da proprio questa definizione definendo diverse classi:

Context

Modella il contesto di esecuzione della macchina a stati, contiene uno stato corrente e fornisce il punto di accessso unico per tutte le richieste di cambio di stato. Uno dei punti di forza del pattern è che dall'esterno non c'è alcun tipo di percezione dello stato in cui la macchina è attualmente. Si possono solamente comandare delle transizioni che il contesto può assorbire o meno. Le transizioni provengono tramite il metodo ChangeStateRequest(StateTrasitionEnum.DEST).

Il contesto deve contenere tutte le informazioni utili alla logica interna per rendere autonoma la macchina a stati ad un eventuale il cambio di stato. Memorizzo nel contesto la richiesta proveniente dall'esterno per fare in modo che il current State possa averne conoscienza. Inoltre posso in questo modo debuggare l'ultima richiesta che la macchina ha avuto.

State

Una classe astratta che contiene un metodo di gestione dello stato Handle. Da questa classe erediteranno tutti gli stati reali che il contesto può assumere.

InitialState

Lo stato iniziale della macchina a stati. Prevede un funzionamento particolare visto che è il primo stato dove la macchina a stati andrà a eseguire. Questo stato prevede la transizione in altri stati solo se un bool stateMachineIsEnabled è abilitato. E' infatti importante in certi casi disabilitare la macchina a stati alle transizioni per esempio quando si incontrino casi di errore.

X_State, Y_State

Due stati di lavoro nei quali la macchina può saltare. Nell'esempio si salta in modo alternato ed incondizionato dallo stato X_State, Y_State. C' è un controllo sul comando di transizione per fare in modo che la macchina transiti dallo X_State verso lo Y_State solo se c'è stato un comando di tipo StateTransitionEnum.TO_STATE_Y. In questa specifica implementazione comandi di transizione consecutivi identici (2 StateTransitionEnum.TO_STATE_Y.) comporteranno un unico cambio di stato ma questa è una mia interpretazione che può essere cambiata a seconda delle varie esigenze. Nello X_State ho implementato per completezza la funzione DoSomethingOnTransaction(Context context) per implementare qualche azione durante la transazione di stato.

Implementazione in C# .NET

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PatternState
{
    class Program
    {
        static void Main(string[] args)
        {
            bool stateMachineEnabled = true;

            Context myContext = new Context(stateMachineEnabled);
            myContext.ChangeStateRequest(StateTransitionEnum.TO_STATE_X);
            myContext.ChangeStateRequest(StateTransitionEnum.TO_STATE_Y);

            Console.ReadKey();
        }
    }

    public enum StateTransitionEnum
    {
        TO_STATE_X = 0,
        TO_STATE_Y = 1,
    }

    public class Context
    {
        private State currentState;
        private bool stateMachineEnabled;
        private StateTransitionEnum stateTransitionEnum;

        public State CurrentState
        {
            get
            {
                return this.currentState;
            }
            set
            {
                this.currentState = value;
#if DEBUG
                Console.WriteLine("CurrentState: " + currentState.GetType().Name);
#endif
            }
        }

        public bool StateMachineEnabled
        {
            get { return stateMachineEnabled; }
        }

        public StateTransitionEnum StateTransitionEnum
        {
            get { return stateTransitionEnum; }
        }

        public Context(bool stateMachineEnabled)
        {
            this.stateMachineEnabled = stateMachineEnabled;
            this.CurrentState = new InitialState();
        }

        public void ChangeStateRequest(StateTransitionEnum stateTransitionEnum)
        {
            this.stateTransitionEnum = stateTransitionEnum;

            this.Request();
        }

        private void Request()
        {
            currentState.Handle(this);
        }
    }

    public abstract class State
    {
        public abstract void Handle(Context messageSwitchContext);
    }

    public class InitialState : State
    {
        public override void Handle(Context context)
        {
            if (context.StateMachineEnabled)
            {
                switch (context.StateTransitionEnum)
                {
                    case StateTransitionEnum.TO_STATE_Y:
                        context.CurrentState = new Y_State();
                        break;
                    case StateTransitionEnum.TO_STATE_X:
                        context.CurrentState = new X_State();
                        break;
                    default:
                        context.CurrentState = new InitialState();
                        break;
                }
            }
        }
    }

    public class X_State : State
    {
        public override void Handle(Context context)
        {
            if (context.StateTransitionEnum == StateTransitionEnum.TO_STATE_Y)
            {
                //I'm switching to state Y
                this.DoSomethingOnTransaction(context);
                context.CurrentState = new Y_State();
            }
        }

        private void DoSomethingOnTransaction(Context context)
        {
            Console.WriteLine("Transaction to " + context.CurrentState.GetType().Name);
        }
    }

    public class Y_State : State
    {
        public override void Handle(Context messageSwitchContext)
        {
            if (messageSwitchContext.StateTransitionEnum == StateTransitionEnum.TO_STATE_X)
            {
                //I'm switching to state X
                messageSwitchContext.CurrentState = new X_State();
            }
        }
    }
}

 

 
 
 
 
 

INFO


Un blog di: MatteoDegliEsposti
Data di creazione: 24/01/2010
 

CERCA IN QUESTO BLOG

  Trova
 

ULTIME VISITE AL BLOG

eugenio78_estN_Y_N_Ik331MatteoDegliEspostiOxumare81raba_ramapsicologiaforensesemprepazzaDivine_Blondecamel_silverfernandez1983andreadialbineamessaggeria.normale
 

CHI PUò SCRIVERE SUL BLOG

Solo l'autore può pubblicare messaggi in questo Blog e tutti gli utenti registrati possono pubblicare commenti.
 
RSS (Really simple syndication) Feed Atom
 
 
 

© Italiaonline S.p.A. 2024Direzione e coordinamento di Libero Acquisition S.á r.l.P. IVA 03970540963