Link link = new SimpleLink(url, texto);
public class Link {
private String url;
private String texto;
// constructor private
private Link(String url, String texto) {
this.url = url;
this.texto = texto;
}
public static Link of(String url, String texto) {
// aca puede ir cualquier mejora:
// podemos retornar siempre el mismo objeto
// o usar un pool de objetos
// o podemos cambiar la implementación
return new Link(url, texto);
}
}
public interface Link {
getUrl();
getTexto();
static Link of(String url, String texto) {
if (url.startsWith("http")) {
return new ExternalLink(url, texto);
}
if (url.contains("@")) {
return new EmailLink(url, texto);
}
if (url.contains("/assets/")) {
return new FileLink(url, texto);
}
return SimpleLink(url, texto);
}
}
public final class Barcos {
// usualmente el parámetro es un Enum
public static Barco of(Tipo tipo) {
switch(tipo) {
case Barco.ACORAZADO:
return new Acorazado();
case Barco.PORTAAVIONES:
return new Portaaviones();
case Barco.SUBMARINO:
return new Submarino();
case Barco.BUQUE:
return new Buque();
case Barco.DESTRUCTOR:
return new Destructor();
default:
throw new AssertionError("Inesperado: " + tipo);
}
}
}
public class Ubicación {
private String dirección;
private String códigoPostal;
private String bloque;
private String apartamento;
private String ciudad;
private String departamento;
}
public class Ubicación {
// código
public static class Builder {
private String dirección;
private String códigoPostal;
private String bloque;
private String apartamento;
private String ciudad;
private String departamento;
// código
}
}
public static class Builder {
private String dirección;
private String ciudad;
private String departamento;
public Builder dirección(String dirección) {
this.dirección = dirección;
return this;
}
public Builder ciudad(String ciudad) {
this.ciudad = ciudad;
return this;
}
public Builder departamento(String departamento) {
this.departamento = departamento;
return this;
}
// código
}
public class Ubicación {
private final String dirección; // final
private final String ciudad;
private final String departamento;
private Ubicación(Builder builder) { // private
this.dirección = builder.dirección;
this.ciudad = builder.ciudad;
this.departamento = builder.departamento;
}
public static class Builder {
// código
public Ubicación build() {
return new Ubicación(this);
}
}
}
Ubicación u =
new Ubicación.Builder()
.dirección("Cll 100 # 7a - 81")
.ciudad("Bogotá")
.build();
Ubicación u2 =
new Ubicación.Builder()
.dirección("Cll 100 # 7a - 81")
.códigoPostal("110125")
.apartamento("101")
.ciudad("Bogotá")
.build();
public class Link {
private String url;
private String text;
public Link(String url, String text) {
this.url = url;
this.text = text;
}
// código
}
Link google =
new Link("Google", "http://google.com");
Link wikipedia =
new Link("Wikipedia", "http://wikipedia.com");
Link twitter =
new Link("Twitter", "http://twitter.com");
¿Notaron el error?
public class Link {
private final String url;
private final String texto;
private Link(Builder builder) {
this.url = builder.url;
this.texto = builder.texto;
}
public static class Builder {
private String url;
private String texto;
public Builder url(String url) {
this.url = url;
return this;
}
public Builder texto(String texto) {
this.texto = texto;
return this;
}
public Link build() {
return new Link(this);
}
}
}
Link google =
new Link.Builder()
.url("http://google.com")
.texto("Google")
.build();
Link twitter =
new Link.Builder()
.texto("Twitter")
.url("http://twitter.com")
.build();
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
// code
}
public class NutritionFacts {
// código
public static class Builder {
// Parámetros requeridos
private final int servingSize;
private final int servings;
// Opcionales - inicializar con valores "default"
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val)
{ calories = val; return this; }
public Builder fat(int val)
{ fat = val; return this; }
public Builder carbohydrate(int val)
{ carbohydrate = val; return this; }
public Builder sodium(int val)
{ sodium = val; return this; }
}
public class NutritionFacts {
// código
public static class Builder {
// Parámetros requeridos
private final int servingSize;
private final int servings;
// Opcionales - inicializar con valores "default"
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val)
{ calories = val; return this; }
public Builder fat(int val)
{ fat = val; return this; }
public Builder carbohydrate(int val)
{ carbohydrate = val; return this; }
public Builder sodium(int val)
{ sodium = val; return this; }
}
public class NutritionFacts {
// código
public static class Builder {
// código
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
this.servingSize = builder.servingSize;
this.servings = builder.servings;
this.calories = builder.calories;
this.fat = builder.fat;
this.sodium = builder.sodium;
this.carbohydrate = builder.carbohydrate;
}
}
NutritionFacts cocaCola =
new NutritionFacts.Builder(240, 8)
.calories(100)
.sodium(35)
.carbohydrate(27)
.build();
// Arrancamos de una interface
// Esta clase permite leer un
// archivo CSV sobre el protocolo FTP
public interface FtpCSVReader {
InputStream getInputStream();
CSVParser fetch(InputStream inputStream);
}
// Esta es la clase que provee la funcionalidad
public class SimpleFtpCsvReader
implements FtpCsvReader {
// código
@Override
public InputStream getInputStream() {
// implementación
}
@Override
public CSVParser fetch(InputStream inputStream) {
// implementación
}
}
public class FtpCsvReaderZippedDecorator implements FtpCsvReader {
private FtpCsvReader csvReader;
// Delegación
public FtpCsvReaderZippedDecorator(FtpCsvReader csvReader) {
this.csvReader = Objects.requireNonNull(csvReader);
}
@Override
public InputStream getInputStream() {
try {
// delegar
InputStream in = csvReader.getInputStream();
// y luego decorar
ZipInputStream zis = new ZipInputStream(in);
zis.getNextEntry();
return zis;
} catch (IOException e) {
throw new FTPServiceException(":(", e);
}
}
@Override
public CSVParser fetch(InputStream inputStream) {
// para métodos no-decorados, simplemente delegar
return csvReader.fetch(inputStream);
}
}
public static FtpCsvReader build(final boolean zipped) {
FtpCsvReader csvReader = new SimpleFtpCsvReader();
return zipped ? new FtpCsvReaderZippedDecorator(csvReader)
: csvReader;
}
public interface Café {
double precio();
}
public abstract class DecoradorCafé
implements Café {
private Café café;
public DecoradorCafé(Café café) {
this.café = Objects.requireNonNull(café);
}
@Override
public double precio() {
return café.precio();
}
}
public class Mocha implements DecoradorCafé {
// código
public double precio() {
return 2.0;
}
}
* * *
public class Latte implements DecoradorCafé {
// código
public double precio() {
return 2.5;
}
}
* * *
public class Expresso implements DecoradorCafé {
// código
public double precio() {
return 1.0;
}
}
public class LecheEntera extends DecoradorCafé {
public LecheEntera(DecoradorCafé decorado) {
super(decorado);
}
public precio() {
return super.precio() + 0.5;
}
}
public class LecheDeslactosada extends DecoradorCafé {
public LecheDeslactosada(DecoradorCafé decorado) {
super(decorado);
}
public precio() {
return super.precio() + 0.6;
}
}
public class Soya extends DecoradorCafé {
public LecheDeslactosada(DecoradorCafé decorado) {
super(decorado);
}
public precio() {
return super.precio() + 0.75;
}
}
public class CremaChantilly extends DecoradorCafé {
public CremaChantilly(DecoradorCafé decorado) {
super(decorado);
}
public precio() {
return super.precio() + 0.25;
}
}
public class ChispasChocolate extends DecoradorCafé {
public ChispasChocolate(DecoradorCafé decorado) {
super(decorado);
}
public precio() {
return super.precio() + 0.3;
}
}
DecoradorCafé mochaSoyaDobleCremaChantilly =
new CremaChantilly(new CremaChantilly(new Soya(new Mocha())));
// 0.25 + 0.25 + 0.75 + 2.0
System.out.println(mochaSoyaDobleCremaChantilly.precio());
DecoradorCafé expressoLecheCremaChantillyChispas =
new CremaChantilly(new ChispasChocolate(new LecheEntera(new Expresso())));
// 0.25 + 0.3 + 0.5 + 1.0
System.out.println(expressoLecheCremaChantillyChispas.precio());
public List<Transacciones> buscarPorId(String userId) {
User user = userBO.buscar(id);
return userBO.transacciones(user); // retorna null
}
public double totalizarTransacciones(String userId) {
// Pre Java 8
double total = 0.0;
// Lanzaría un NPE en la actual implementación
for (Transacción t : buscarPorId(userId)) {
total += t.monto();
}
return total;
}
public List<Transacciones> buscarPorId(String userId) {
User user = userBO.buscar(id);
List<Transacciones> transacciones = userBO.transaccion(user);
return transacciones != null
? transacciones
: Collections.emptyList();
}
public double totalizarTransacciones(String userId) {
// Pre Java 8
double total = 0.0;
// Código no lanza NPE, retorna 0
// si el usuario no tiene transacciones
for (Transacción t : buscarPorId(userId)) {
total += t.monto();
}
return total;
}
public interface Link {
String getUrl();
String getTexto();
boolean isVacío();
public static EMPTY = new Link {
public String getUrl() {
return "";
}
public String getTexto() {
return "";
}
public isVacío() {
return true;
}
}
}
public SimpleLink implements Link {
private String url;
private String texto;
public SimpleLink(String url, String texto) {
this.url = url;
this.texto = texto;
}
public String getUrl() {
return url;
}
public String getTexto() {
return texto;
}
public boolean isVacío() {
return false;
}
}
public static Link of(String url, String texto) {
if (url.isEmpty()) {
return Link.EMPTY;
}
return new SimpleLink(url, texto);
}
<c:if test="${link.vacío}">
<a href="${link.url}">${link.texto}</a>
</c:if>
<a href="${link.url}">${link.texto}</a>
Algunos FW quitan un vínculo
si el atributo href no tiene valor