miércoles, 6 de junio de 2007

Los Patrones Estrategia y Decorador trabajando en conjunto

A continuación daré un ejemplo de como utilizar estos dos patrones de forma conjunta en C#, aunque se podría aplicar en VFP de forma muy sencilla siguiendo la misma lógica que venimos trabajando en los distintos artículos.





Vamos a reutilizar todas las clases que venimos publicando en el artículo de estategia, decorador y puente.




La pantalla anterior es como luce nuestra aplicación. Veamos el código para lograrlo:





using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using estrategia;


namespace WindowsApplication1
{
public partial class CodigoDinamico : Form
{
public CodigoDinamico()
{
InitializeComponent();
}

private Estrategia _Procesador= new Estrategia();

public Estrategia Procesador
{
get { return _Procesador; }
set { _Procesador = value; }
}

private void asignarFuncionalidad()
{
Lis<String> Items = new List<String>();
if (optApeNom.Checked) { Items.Add("Puente"); }
if (optNomApe.Checked) { Items.Add("NombreApellido"); }
if (optEnriquecido.Checked) { Items.Add("Enriquecido"); }
if (chkNumera.Checked) { Items.Add("AgregarNumeracion"); };
if (chkNacion.Checked) { Items.Add("AgregarNacionalidad"); };
Procesador = Dinamico.Proceso(Items);
if (chkNacion.Checked)
{
AgregarNacionalidad Nacionalidad = (AgregarNacionalidad)Procesador.Contexto.MiClase;
Nacionalidad.Nacionalidad = txtNacion.Text;
}

}

private void btn1_Click(object sender, EventArgs e)
{
asignarFuncionalidad();
txtSalida.Text = this.Procesador.ProcesarNombres(txtNombre.Text, txtApellido.Text);
}

private void chkNacion_CheckedChanged(object sender, EventArgs e)
{
if (chkNacion.Checked)
{
txtNacion.ReadOnly = false;
}
else
{
txtNacion.ReadOnly = true;
}
}


}
}
 
Como verán, en el botón btn1 siempre llamamos a asignarFuncionalidad antes de llamar a nuestra función. Esta función crea una lista genérica de String y se la pasa al metódo Estático "Proceso" de la Clase Dinamico. Veamos esta nueva clase:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace estrategia
{
public class Dinamico
{
public static Estrategia Proceso(List<String> Decoradores)
{
Assembly Ass = Assembly.GetExecutingAssembly();
Object Estra = Ass.CreateInstance("estrategia." + Decoradores[0].Trim());
Decoradores.Remove(Decoradores[0]);
Object[] o = new Object[1];
o[0] = Estra;
foreach (String deco in Decoradores)
{
o[0] = Ass.CreateInstance("estrategia." + deco, false, BindingFlags.CreateInstance,null, o, null, null);
}
Estrategia st = new Estrategia(new contexto((IProcesarNombres)o[0]));
return st;
}
}
}
La función genera la estrategia y los decoradores mediante Reflection.
Con el primer elemento de la lista selecciona la estrategia y con el resto agrega los decoradores. De esta forma se puede crear dinámicamente toda la funcionalidad. 
Si se crea una nueva clase solo se debe para el nombre de la misma en la lista genérica y sale funcionando sin tocar casi nada del código.
Este tipo de tecnología tiene muchas aplicaciones y que seguro ustedes ya deben estar pensando.

No hay comentarios.: