domingo, 13 de julio de 2008

FACTORY PATTERN

Este pattern se utiliza para la creación de objetos , nos permite la creación de clases sin especificar la clase exacta del objeto a ser creado. Este pattern define una interfase para crear un objeto, pero las subclases son las que deciden que clase instanciar.

Ejemplo :


public abstract class Empleado
{
// Este metodo va a ser implementado en las clases
// que van a heredar de Empleado
public abstract int Sueldo();

public enum TipoEmpleado
{
Programador,
Funcional,
Analista
}

// Aca implementamos Factory , este va a devolver Empleados
// que se generan segun el parametro recibido.
// El resultado siempre sera el mismo (Empleado) , varia la
// forma en como se genera la clase.
public static Empleado EmpleadoFactory(TipoEmpleado tipo)
{
// Segun el tipo recibido generamos el objeto Empleado
// de una clase en particular
switch (tipo)
{
case TipoEmpleado.Programador:
return new Programador();
case TipoEmpleado.Funcional:
return new Funcional();
case TipoEmpleado.Analista:
return new Analista();
}
throw new Exception("Tipo no Valido");

}

}


public class Programador : Empleado
{
public override int Sueldo()
{
return 15;
}
}

public class Funcional : Empleado
{
public override int Sueldo()
{
return 20;
}
}

public class Analista : Empleado
{
public override int Sueldo()
{
return 30;
}
}


Codigo Cliente :

static void Main(string[] args)
{
// De la Factory Empleado hacemos que nos devuelva
// un Empleado del tipo programador
Empleado programador = Empleado.EmpleadoFactory(Empleado.TipoEmpleado.Programador);

Console.WriteLine("Sueldo Programador :" + programador.Sueldo().ToString());


// De la Factory Empleado hacemos que nos devuelva
// un Empleado del tipo funcional
Empleado funcional = Empleado.EmpleadoFactory(Empleado.TipoEmpleado.Funcional);

Console.WriteLine("Sueldo Funcional :" + funcional.Sueldo().ToString());


Console.ReadLine();
}

sábado, 12 de julio de 2008

ABSTRACT FACTORY PATTERN

Este patrón se utiliza cuando debemos generar distintas familias de objetos , dejando esto a la interface de la factory y sacándole dicha responsabilidad al cliente.

El cliente tan solo de dedica a crear un determinado tipo de objeto , mientras que la abstract factory se dedica a implementar y especificar a que familia pertenece el mismo .De esta forma podemos generar objetos del mismo tipo , pero generados desde distintas clases .O se tienen distintas implementaciones y estas son manejadas por la Factory.


El siguiente ejemplo , consta de una clase Abstract Factory que nos permite generar Empleados y Clientes .En base a esta clase generamos las Factory de Personas según la Empresa (mediante herencia), que estas serán las que implementen los métodos para crear las clases Clientes y Empleados .Cada una de estas Factory lo implementara según sus propias reglas .O sea acá es cuando la factory implementa el objeto según la familia que corresponda , sabiendo que siempre va a devolver un Cliente o Empleado , sin esto estar atado a la Empresa que lo genere .Esto hace que el cliente que consuma el factory solo se preocupa por instanciar la clase que necesite , mientras que la factory se encarga de la generación de la misma.


Codigo Clase Factory :



namespace AbstractFactoryPatternLibrary
{
public abstract class PersonaFactory
{
// Nos aseguramos de que todas las clases Factory van
// a generar objetos del tipo Empleado y Cliente
public abstract Empleado BuildEmpleado();
public abstract Cliente BuildCliente();
}


// Implementamos Abstract Factory
// Mediante PersonaFactory sabemos los
// objetos que debe generar la clase.
// En este caso es una factory que lo implementa
// segun los requerimientos de Empresa1
public class Empresa1PersonaFactory:PersonaFactory
{
// Implementamos los contructores que devuelven
// los objetos establecidos en la Abstract Factory
// En este caso se generan para el empleado tipo
// EmpleadoEmpresa1
public override Empleado BuildEmpleado()
{
Empleado emp = new EmpleadoEmpresa1();
return emp;
}

public override Cliente BuildCliente()
{
Cliente cli = new ClienteEmpresa1();
return cli;
}
}



// Cumple el mismo proposito que Empresa2PersonaFactory.
// Aca podemos ver como este pattern nos permite realizar
// una implementacion distinta del primer Factory , generando
// los mismos tipos de clases hacia el cliente , pero creandolo
// desde otras clases.
public class Empresa2PersonaFactory : PersonaFactory
{
public override Empleado BuildEmpleado()
{
Empleado emp = new EmpleadoEmpresa2();
return emp;
}

public override Cliente BuildCliente()
{
Cliente cli = new ClienteEmpresa2();
return cli;
}
}




public class ClienteEmpresa1:Cliente
{
public override void VerificarCuenta()
{
Console.WriteLine("Verificando Cuenta cliente Empresa1");
}
}

public class EmpleadoEmpresa1:Empleado
{
public override void CalcularSueldo()
{
Console.WriteLine("Calculando Sueldo empleado Empresa1");
}
}

public class ClienteEmpresa2:Cliente
{
public override void VerificarCuenta()
{
Console.WriteLine("Verificando Cuenta cliente Empresa2");
}
}

public class EmpleadoEmpresa2:Empleado
{
public override void CalcularSueldo()
{
Console.WriteLine("Calculando Sueldo empleado Empresa2");
}
}


// Clases abstract , van a ser las clases base
// Desde donde van a heredar los Clientes y
// Empleados de TODAS las Empresas.
// De esta forma cada Empresa va a definir el
// campo segun sus reglas de negocio.
public abstract class Empleado
{
// Las clases van a tener que implementar este metodo
public abstract void CalcularSueldo();
}

public abstract class Cliente
{
public abstract void VerificarCuenta();
}
}


Codigo Aplicacion de Consola que consume nuestro Factory :

class Program
{
static void Main(string[] args)
{

// Generamos Factory de Personas para Empresa1
// mediante este objeto vamos a poder generar Clientes y Empleados
// con la estructura que implementa la Empresa1
PersonaFactory personaFactoryEmpresa1 = new Empresa1PersonaFactory();

// Utilizamos la Factory para generar Clientes y Empleados
Cliente clienteEmpresa1 = personaFactoryEmpresa1.BuildCliente();
Empleado empleadoEmpresa1 = personaFactoryEmpresa1.BuildEmpleado();

empleadoEmpresa1.CalcularSueldo();

// Factory para CLientes y Empleados del tipo Empresa2
PersonaFactory personaFactoryEmpresa2 = new Empresa2PersonaFactory();

//Generamos Clientes y Empleados para Empresa2
Cliente clienteEmpresa2 = personaFactoryEmpresa2.BuildCliente();
Empleado empleadoEmpresa2 = personaFactoryEmpresa2.BuildEmpleado();

clienteEmpresa2.VerificarCuenta();
empleadoEmpresa2.CalcularSueldo();

// Otro ejemplo

// En la clase Gestor tenemos un metodo que no espera un Cliente
// ni un Empleado.El mismo se encarga de Generarlos , tan solo nesesita
// un objeto Factory.
// Por lo que este Metodo queda abierto a que se le pueda pasar cualquier
// Factory sin importar la Empresa
Gestor miGestor = new Gestor();

miGestor.GenerarCliente(personaFactoryEmpresa1);

Console.ReadLine();

}
}

class Gestor
{
public void GenerarCliente(PersonaFactory persona)
{
Cliente cliente = persona.BuildCliente();
Console.WriteLine("Cliente Generado desde el Gestor");
}
}