public class Link {
// código
public String getUrl() { ... }
public String getTexto() { ... }
public String getTarget() { ... }
public boolean isVacío() { ... }
}
public class EmailLink extends Link {
// código
@Override
public String getUrl() {
return "mailto:" + super.getUrl();
}
}
public class Rectángulo {
private double a;
private double b;
public void setA(double a) { this.a = a; }
public void setB(double b) { this.b = b; }
public double getA() { return a; }
public double getB() { return b; }
}
public class Cuadrado {
private double lado;
// hay 2 maneras de modificar el valor
// de lado pero por los nombres de los
// métodos no es claro
public void setA(double a) { this.lado = a; }
public void setB(double b) { this.lado = b; }
// igualmente, hay 2 maneras de
// obtener el valor de lado
public double getA() { return lado; }
public double getB() { return lado; }
}
void foo(Rectángulo r) {
r.setA(5);
r.setB(10);
r.getA(); // debería ser 5
r.getB(); // debería ser 10
}
* * *
foo(new Cuadradro()) // rompe las expectativas
public class Punto {
private double x;
private double y;
public double distancia(Punto otro) {
return Math.sqrt(Math.pow(x - otro.x), 2)
+ Math.pow(y - otro.y), 2));
}
}
public class Vehículo {
private Punto punto; // composición
public double distancia(Vehículo otro) {
// delegación
return punto.distancia(otro.punto);
}
}
Para reutilizar código de
la clase A en la clase B
Use composición para que
la clase B tenga una instancia
de la clase A
Utilice delegación
public interface Link {
String getUrl();
String getTexto();
String getTarget();
boolean isVacío();
}
public abstract class AbstractLink implements Link {
private String url;
private String texto;
public AbstractLink(String url, String texto) {
this.url = Objects.requireNonNull(url);
this.texto = Objects.requireNonNull(texto);
}
public String getUrl() {
return url;
}
public String getTexto() {
return texto;
}
public boolean isVacío() {
return url.isEmpty();
}
}
public class AcmeLink extends AbstractLink {
public AcmeLink(String utl, String texto) {
super(url + ".html", texto);
}
public getTarget() {
return "_self";
}
}
public class ExternalLink extends AbstractLink {
public AcmeLink(String utl, String texto) {
super(url, texto);
}
public getTarget() {
return "_blank";
}
}
public class EmailLink extends AbstractLink {
public EmailLink(String utl, String texto) {
super("mailto:" + url, texto);
}
public EmailLink(String url) {
this(url, url);
}
public getTarget() {
return "_blank";
}
}
public class FileLink extends AbstractLink {
public FileLink(String utl, String texto) {
super(url, texto);
}
public FileLink(String url) {
super(url, "download");
}
public getTarget() {
return "_self";
}
}
public class Image {
private String source;
private String altText;
public Image(String source, String altText) {
this.source = source;
this.altText = altText;
}
public String getSource() {
return source;
}
public String getAltText() {
return altText;
}
public boolean isVacío() {
return source.isEmpty();
}
}
public class ImageLink {
private Image image;
private Link link;
public ImageLink(Image image, Link link) {
this.image = image;
this.link = link;
}
public String getSource() { return image.getSource(); }
public String getAltText() { return image.getAltText(); }
public String getUrl() { return link.getUrl(); }
public String getTexto() { return link.getTexto(); }
public String getTarget() { return link.getTarget(); }
public boolean isVacío() {
return link.isVacío() || image.isVacío();
}
}
/**
* Este método acepta cualquier tipo
* que sea una List, no importa cual
*/
public void foo(List<String> data) {
// code
}
/**
* Este método retorna una List.
* La implementación puede cambiar,
* pero no importa porque seguirá
* siendo una List
*/
public List<String> foo() {
// code
}
public class Foo {
/**
* Esta clase se implementa con una List
* Cual List es un detalle de
* implementación que puede cambiar
* en cualquier momento.
*/
private List<String> data;
// code
}
public class ImageLink {
private Image image;
private Link link;
public ImageLink(Image image, String url, String texto) {
// la implementación es fija
// no hay flexibilidad
this.link = new ExternalLink(url, texto);
this.image = image;
}
}
public class ImageLink {
private Image image;
private Link link;
public ImageLink(Image image, Link link) {
// la implementación es inyectada
// la responsabilidad es del
// código cliente
this.link = link;
this.image = image;
}
}
interface Link {}
abstract class AbstractLink implements Link {}
class SimpleLink extends AbstractLink {}
class EmailLink extends SimpleLink {}