En Java el uso de interfaces es algo común en la programación del día a día . Sin embargo también es bastante común tener muchas dudas de para que sirve un interface . Normalmente nos podemos encontrar con definiciones como la siguiente de Interface.
Interface : Conjunto de métodos Java que una clase debe implementar .Una interface define un contrato que una clase tiene que cumplir al implementar los métodos .
Definiciones similares a estas las podemos encontrar por decenas. Una vez leida la definición los programadores suelen ir corriendo a echar un vistazo al código fuente a ver si consiguen entenderlo mejor y se encuentran con algo como lo siguiente.
package com.arquitecturajava; public interface Copiable { public void copiar(); public void copiarColor(); }
package com.arquitecturajava; public class CopiadoraProfesional implements Copiable { @Override public void copiar() { System.out.println("la copiadora copia"); } @Override public void copiarColor() { System.out.println("la copiadora copia a color"); } }
Después de revisar el código varias veces mucha gente entiende como se implementa un interface . Lo dificil es entender para que sirve y como usarlo. Es como si nos dijeran que tenemos un aparato que tiene 4 cilindros alineados recubiertos de una goma plastica y soldada con un metal a los cuales se les transfiere energia …. para decir que hablamos de un “Coche”. Normalmente las personas no hablamos así sino que decimos un Coche es un aparato que sirve para desplazarse mas rápido (eso se entiende mejor).
Java Interfaces (Uso)
¿Para que se usa un interface en Java? .Un interface en Java se usa para añadir flexibilidad al programa que estamos construyendo. Supongamos que tenemos el siguiente bloque de código.
package com.arquitecturajava; public class Compra { private double importe; private String tipo; public String getTipo() { return tipo; } public void setTipo(String tipo) { this.tipo = tipo; } public double getImporte() { return importe; } public void setImporte(double importe) { this.importe = importe; } public Compra(double importe, String tipo) { super(); this.importe = importe; this.tipo = tipo; } public double descuento() { double descuento; if (tipo.equals("tienda")) { if (importe > 0 && importe < 100) { descuento = 10; } else { descuento = 20; } } else { if (importe > 0 && importe < 100) { descuento = 20; } else { descuento = 30; } } return importe -importe *descuento/100; } }
Se trata de la clase Compra que hace un calculo del descuento que nos aplican dependiendo del tipo de Compra que realicemos (Tienda u Online)
Aunque en principio el método es completamente válido y podemos ver como se usa en un programa de consola.
package com.arquitecturajava; public class Principal { public static void main(String[] args) { Compra c= new Compra(1000,"tienda"); System.out.println(c.descuento()); } }
Nos podemos encontrar con problemas si las especificaciones cambian y se añaden mas tipos de descuentos . Por ejemplo descuento por ser empleado y descuento por ser directivo de la empresa.Podemos añadir esta funcionalidad a la clase pero el método “descuento” cada vez será mas grande y mas dificil de entender.
Puntos de extensibilidad (Plugin-points)
Para solventar este problema podemos reubicar la lógica de negocio de la aplicación diseñando un interface que sirva como punto de extensibilidad para la funcionalidad del descuento.
El diagrama no es sencillo de entender de entrada así que vamos a desglosarlo con código.Empezamos con la definición del interface.
package com.arquitecturajava.estrategia; public interface TipoDescuento { public double importeDescontar(Compra c); }
Este interface recibe en su método importeDescontar el concepto de Compra. Para después calcular el descuento. Una vez visto el código del interface vamos a ver dos de sus implementaciones.
package com.arquitecturajava.estrategia; public class DescuentoInternet implements TipoDescuento { @Override public double importeDescontar(Compra c) { double descuento; if (c.getImporte() > 0 && c.getImporte() < 200) { descuento = 20; } else { descuento = 30; } return c.getImporte() * descuento / 100; } }
package com.arquitecturajava.estrategia; public class DescuentoTienda implements TipoDescuento { public double importeDescontar(Compra c) { double descuento; if (c.getImporte() > 0 && c.getImporte() < 100) { descuento = 10; } else { descuento = 20; } return c.getImporte() * descuento / 100; } }
Creadas estas clases ,modificaremos la clase Compra para que se apoye en el nuevo interface (TipoDescuento).
package com.arquitecturajava.estrategia; public class Compra { private double importe; public double getImporte() { return importe; } public void setImporte(double importe) { this.importe = importe; } public Compra(double importe) { super(); this.importe = importe; } public double descuento(TipoDescuento tipoDescuento) { return importe- tipoDescuento.importeDescontar(this); } }  
Cuando nosotros queramos aplicar un descuento será tan sencillo como construir el siguiente código a nivel del programa principal.
package com.arquitecturajava.estrategia; public class Principal { public static void main(String[] args) { Compra c= new Compra(1000); System.out.println(c.descuento(new DescuentoTienda())); } }
Si queremos crear un nuevo tipo de descuento simplemente diseñaremos una nueva clase que implemente el interface .
package com.arquitecturajava.estrategia; public class DescuentoDirectivo implements TipoDescuento { public double importeDescontar(Compra c) { return c.getImporte() * 50 / 100; } }
Creado el nuevo tipo de descuento simplemente nos queda aplicarle en el código .
package com.arquitecturajava.estrategia; public class Principal { public static void main(String[] args) { Compra c= new Compra(1000); System.out.println(c.descuento(new DescuentoDirectivo())); } }
Es por ello que a los interfaces también se les conoce a nivel de diseño como plugin-points o puntos de extensibilidad.
Brillante explicacion de interface!!! muy didactico!!
[…] artículos relacionados: Entendiendo los constructores en Java ,El concepto de Java Interface ,Java […]
DescuentoTienda le falta el @override
no sería obligatorio aunque si recomendable 🙂
[…] artículos relacionados: Java BigInteger , Java Interface , Java […]
[…] Java interfaces y flexibilidad […]
Excelente tutorial que explica de paso como desacoplar una aplicación, mi consulta es hasta que punto debo hacer uso de las interfaces para desacoplar el código.
Saludos, buena página.
Ojala hubiera una respuesta definitiva 🙂 . Desde mi punto de vista esta muy ligado a la evolución de la aplicación será ella la que en un punto determinado pida mas flexibilidad en una zona y necesites de esos puntos de extensibilidad
[…] con los métodos de instancia .La consulta tiene como punto de partida otros de los articulos el de el concepto de interface .Me ha parecido interesante hablar un poco de este tema porque sobre todo a la gente que comienza […]
Buen aporte Sr Cecilio
gracias 🙂
Siempre sigo tus posts, excelente cada uno de ellos…
gracias 🙂
Añadir que en el ejemplo que propone Cecilio para explicar el uso de interfaces está haciendo uso de un patrón de diseño bastante útil (patrón de diseño strategy), y que ahorra bastante tiempo a la hora de codificar distintas funcionalidades a una estrategia de negocio, en este caso aplicar un descuento en una compra. Si haceis un buen uso de las interfaces podéis garantizar una mayor escalabilidad del sistema. Animo a Cecilio hacer algún día una entrada con los patrones de diseño más útiles 🙂
lo apunto como idea para hablar de algún patron 🙂
sería genial 🙂
+1
Me uno a la petición de los patrones más usados.
Pero sobre todo, gracias a tu aportación con esta artículo tan bien ejemplificado, el mundo de desarrollo software es infinito y a veces demasiado mecánico, sin pararnos a pensar en el porqué de su uso.
Salu2
gracias 🙂 . Me apunto la idea
Más claro ni el agua! Una cosa es saber implementarlas y otra por qué o con qué fin.
Saludos!
gracias
Te comento que sigo cada una de tus publicaciones que llegan a mi buzón y me gusta la manera en que explicas los conceptos. Excelente enseñador
gracias
Muy entendible el ejemplo sobre interfacess y muy claro, gracias por ese aporte.
Me gustaría que ejemplificarás el tema de
-clases abstractas
-atributos protected, static o final también a nivel de clases éstos conceptos.
Gracias por el conocimiento y ejemplificación
Intentare sacar algún hueco para algún tema de estos 🙂