iberck
3/29/2018 - 5:58 AM

Técnica del doble despacho

Técnica del doble despacho

Sirve para quitar los operadores instanceof de un método para respetar el principio open/closed convirtiendo cada pedazo de código en un método dentro de la misma clase que contenía el método con los instanceof.

Los archivos de este snippet demuestran un ejemplo correcto de la técnica de doble despacho. También se pudo haber definido cómo visita el recepcionista a un hombre y a una mujer en las clases Hombre y Mujer, respetando el principio open/closed pero delegando la implementación de cómo visita el recepcionista al Hombre y a la Mujer en dichas clases, dando la responsabilidad del Recepcionista al Hombre y a la Mujer.

Qué pasa si ahora la persona tuviese que aceptar no solo a un Recepcionsta sino también a un Camarero, a un Gerente, y a un Cajero. Si agregaramos múltiples métodos dentro de Hombre/Mujer para aceptar a todos los roles, crearíamos un alto acoplamiento de Hombre/Mujer hacia ellos. La solución es crear una interfaz llamada VisitadorPersona que sería la interfaz con la que trabajaría el Hombre/Mujer y Recepcionsta,Camarero,Gerente,Cajero implementarían a VisitadorPersona.

import java.text.NumberFormat;

public class Recepcionista {

	public void recibir(Persona persona) {
		// El objetivo es eliminar el instanceof y crear métodos DENTRO DE ESTA MISMA CLASE
		// De acuerdo al tipo de objeto son las operaciones que se deben ejecutar
//		if (persona instanceof Hombre) {
//			System.out.println("hombre bienvenido sea usted caballero");
//			recibirPropina(5);
//		} else if (persona instanceof Mujer) {
//			System.out.println("mujer bienvenida guapa, es usted bellisima");
//			mujer.sonrojar();
//		}
		
		persona.aceptar(this);
	}

	public void agradecerVisita() {
		System.out.println("gracias por venir a este su restaurante");
	}

	public void recibirPropina(double cantidad) {
		NumberFormat format = NumberFormat.getCurrencyInstance();
		String cant = format.format(cantidad);
		System.out.println("recepcionista: he recibido " + cant);
	}
	
	public void visitar(Hombre hombre) {
		System.out.println("hombre bienvenido sea usted caballero");
		recibirPropina(5);
	}
	
	public void visitar(Mujer mujer) {
		System.out.println("mujer bienvenida guapa, es usted bellisima");
		mujer.sonrojar();
	}
	
}
public abstract class Persona {

	public void saludar() {
		System.out.println("buenas tardes");
	}

	public void despedirse() {
		System.out.println("hasta luego!!!!");
	}

	public abstract void aceptar(Recepcionista recepcionista);
}
public class Mujer extends Persona {

	public void sonrojar() {
		System.out.println("me sonroja todita!");
	}

	@Override
	public void aceptar(Recepcionista recepcionista) {
		recepcionista.visitar(this);
	}
}
public class Hombre extends Persona {

	@Override
	public void aceptar(Recepcionista recepcionista) {
		recepcionista.visitar(this);
	}

}
import java.util.Random;

public class Restaurante {

	private Recepcionista recepcionista;

	public static void main(String[] args) {
		Restaurante restaurante = new Restaurante();
		restaurante.recepcionista = new Recepcionista();

		Random random = new Random(System.currentTimeMillis());
		for (int i = 0; i < 5; i++) {
			Persona persona;
			if (random.nextInt(2) == 0) {
				persona = new Hombre();
			} else {
				persona = new Mujer();
			}
			restaurante.simularEscenario(persona);
		}
	}

	private void simularEscenario(Persona persona) {
		persona.saludar();
		recepcionista.recibir(persona);
		persona.despedirse();
		recepcionista.agradecerVisita();
		System.out.println("-------------------");
		System.out.println("pasa un tiempo...");
		System.out.println("-------------------");
	}

}