lunes, 6 de julio de 2015

Patrón de Diseño Builder con Harbour

Seguimos con nuestros patrones de diseño. En este post veremos como implementar el patrón de diseño Builder, del tipo creacional.

Como Patrón de diseño, el patrón builder (Constructor) es usado para permitir la creación de una variedad de  objetos complejos desde un objeto fuente (Producto), el objeto fuente se compone de una variedad de partes que contribuyen individualmente a la creación de cada objeto complejo a través de un conjunto de llamadas a interfaces comunes de la clase Abstract Builder.
https://es.wikipedia.org/wiki/Builder_%28patr%C3%B3n_de_dise%C3%B1o%29          

Como siempre, podemos el código que muestra el uso de este patrón;
#include "hbclass.ch"

/* ABSTRACT BUILDER */
CLASS ROBOT
 
    // Metodos que se tienen que declarar en la clase heredada 
      METHOD Trabajar() VIRTUAL       
      METHOD CargarAcciones() VIRTUAL

 END CLASS

/* ----------------------------------------------------  */
CLASS ROBOT_HAMBUERGUESA FROM ROBOT
      DATA Lista_Acciones

      METHOD New() INLINE Self

      METHOD iniciar  HIDDEN
      METHOD getIngredientes HIDDEN
      METHOD Armar    HIDDEN
      METHOD Revisar  HIDDEN
      METHOD Terminar HIDDEN
     
      METHOD CargarAcciones() // Sobrecargado
      METHOD Trabajar()       // Sobrecargado

END CLASS

METHOD Iniciar() CLASS ROBOT_HAMBUERGUESA
  ? "Iniciando hambuerguesa"
RETURN nil

METHOD getIngredientes() CLASS ROBOT_HAMBUERGUESA
  ? "Coge Ingredientes"
RETURN nil

METHOD Armar() CLASS ROBOT_HAMBUERGUESA
  ? "Arma"
RETURN nil

METHOD Revisar() CLASS ROBOT_HAMBUERGUESA
  ? "Revisar"
RETURN nil

METHOD Terminar() CLASS ROBOT_HAMBUERGUESA
  ? "Terminar"
RETURN nil

METHOD CargarAcciones( Lista ) CLASS ROBOT_HAMBUERGUESA
  ::Lista_Acciones := Lista
RETURN nil

METHOD Trabajar() CLASS ROBOT_HAMBUERGUESA
     Local nAccion

     ::iniciar()

     for each nAccion in ::Lista_Acciones
         do case
            case nAccion = 1
                 ::getIngredientes()
            case nAccion = 2
                 ::Armar()
            case nAccion = 3
                 ::Revisar()
            otherwise
                 ? "No existe accion a realizar"
         end case
     next

     ::Terminar()

RETURN nil


/* ----------------------------------------------------  */
CLASS ROBOT_HOTDOG FROM ROBOT
      DATA Lista_Acciones

      METHOD New() INLINE Self

      // Como ejemplo, al ser metodos privados, podemos tener otros nombres
      METHOD Start  HIDDEN
      METHOD getParts HIDDEN
      METHOD build    HIDDEN
      METHOD check  HIDDEN
      METHOD finish HIDDEN
     
      METHOD CargarAcciones() // Sobrecargado
      METHOD Trabajar()       // Sobrecargado

END CLASS

METHOD Start() CLASS ROBOT_HOTDOG
  ? "Start HotDog"
RETURN nil

METHOD getParts() CLASS ROBOT_HOTDOG
  ? "get Pars"
RETURN nil

METHOD build() CLASS ROBOT_HOTDOG
  ? "Build"
RETURN nil

METHOD check() CLASS ROBOT_HOTDOG
  ? "check"
RETURN nil

METHOD finish() CLASS ROBOT_HOTDOG
  ? "finish"
RETURN nil

METHOD CargarAcciones( Lista ) CLASS ROBOT_HOTDOG
  ::Lista_Acciones := Lista
RETURN nil

METHOD Trabajar() CLASS ROBOT_HOTDOG
     Local nAccion

     ::Start()

     for each nAccion in ::Lista_Acciones
         do case
            case nAccion = 1
                 ::getParts()
            case nAccion = 2
                 ::build()
            case nAccion = 3
                 ::check()
            otherwise
                 ? "No existe accion a realizar"
         end case
     next

     ::finish()

RETURN nil

/* ----------------------------------------------------  */
CLASS BUILDER
      DATA Acciones
      DATA ROBOT

      METHOD New() CONSTRUCTOR
      METHOD SetRobot( i )
      METHOD addGetIngredientes inline aadd( ::Acciones, 1 )
      METHOD addArmar           inline aadd( ::Acciones, 2 )
      METHOD addRevisar         inline aadd( ::Acciones, 3 ) 
      METHOD addImposible       inline aadd( ::Acciones, 100 )

      METHOD getRobot()

END CLASS

METHOD New() CLASS BUILDER
    ::Acciones := {}
RETURN Self

/* Crea un robot segun solicitado */
METHOD SetRobot( i ) CLASS BUILDER
    do case
       case i = "1"
            ::robot := ROBOT_HAMBUERGUESA():New()
       case i = "2"
            ::robot := ROBOT_HOTDOG():New()

    end case
RETURN nil

METHOD getRobot() CLASS BUILDER
   
     ::robot:CargarAcciones( ::Acciones )

RETURN ::robot


/* ----------------------------------------------------  */
// Ejemplo de Implementación : ./test 1

function Main( cRobot )     Local oRobot
     Local oBuilder := BUILDER():New()

     oBuilder:SetRobot( cRobot )
     oBuilder:addRevisar()
     oBuilder:addImposible()
     oBuilder:addGetIngredientes()
     oBuilder:addArmar()
     oBuilder:addRevisar()

     oRobot := oBuilder:getRobot()
     oRobot:Trabajar()

return nil

No hay comentarios:

Publicar un comentario

Android y Git. Disponer del hash automáticamente.

Una de las cosas a las que estoy acostumbrado, es tener siempre en mi código, el hash/tag/versión del control de versiones que estoy usan...