usar - Java 8: interfaz con métodos estáticos en lugar de clase estática de utilidades
utilidad de static en los programas en java (4)
El objetivo principal de las interfaces es proporcionar un tipo y un vocabulario de operaciones (métodos) en ese tipo. Son útiles y flexibles porque permiten múltiples implementaciones, y de hecho están diseñados para permitir implementaciones que de otro modo no están relacionadas en la jerarquía de clases.
La pregunta pregunta
¿Es correcto tener una interfaz que no será implementada por nadie ...?
Esto me parece que va en contra del grano de las interfaces. Uno debería mirar alrededor de la API para determinar que no hay clases que implementen esta interfaz, y que no hay productores o consumidores de esta interfaz. Alguien podría estar confundido e intentar crear una implementación de la interfaz, pero por supuesto no llegarían muy lejos. Si bien es posible tener una "interfaz de utilidad" con todos los métodos estáticos, esto no es tan claro como el antiguo idioma de clase final no constructivo. La ventaja de este último es que la clase puede exigir que nunca se creen instancias.
Si observa las nuevas API de Java 8, verá que aún se utiliza la expresión idiomática de clase final a pesar de la posibilidad de agregar métodos estáticos en las interfaces.
Los métodos estáticos en las interfaces se han utilizado para cosas como los métodos de fábrica para crear instancias de esas interfaces, o para los métodos de utilidad que tienen aplicabilidad general en todas las instancias de esas interfaces. Por ejemplo, vea las interfaces Stream
y Collector
en java.util.stream
. Cada uno tiene fábricas estáticas: Stream.of()
, Stream.empty()
y Collector.of()
.
Pero también tenga en cuenta que cada uno tiene clases StreamSupport
y Collectors
. Estas son clases de utilidad puras, que contienen solo métodos estáticos. Podría decirse que podrían fusionarse en las interfaces correspondientes, pero eso llenaría las interfaces y nublaría la relación de los métodos contenidos en las clases. Por ejemplo, StreamSupport
contiene una familia de métodos estáticos relacionados que son todos adaptadores entre Spliterator
y Stream
. Combinar estos en Stream
probablemente haría las cosas confusas.
¿Cuál es la mejor práctica en Java 8 cuando necesito un montón de métodos de utilidad sin estado? ¿Es correcto tener una interfaz que no será implementada por nadie, es decir, public interface Signatures
public interface Environments
y public interface Environments
, o es mejor hacerlo de la forma anterior? public final class Signatures
public final class Environments
con constructores privados || enums?
En un buen diseño orientado a objetos, no hay muchos (si los hay) métodos de utilidad sin estado.
La mejor técnica con la que he llegado a tratar es usar state (Objects) para manejar la función.
Entonces, en lugar de hacer
Temperature.farenheitFromCelcius(...);
hago
public class FarenheitFromCelcius implements Function<Celcius, Farenheit> {
public Farenheit apply(Celcius celcius) {
return new Farenheit(5 * celcius.getValue() / 9 + 32);
}
}
Esto tiene algunas ventajas. Una de ellas es que se puede descargar de la memoria mucho más fácilmente. Otro ser que puede guardar en el número de interfaces de identificación de tipo, puede pasar métodos de utilidad entre métodos, y un ser final que puede aprovechar la jerarquía de tipo de Java.
Los costos son mínimos Básicamente, tienes que cambiar la forma en que se aplica el método.
public <T> R convertTemp(T temp, Function<T, R> conversion) {
return conversion.apply(temp);
}
Naturalmente, nunca escribirías un método completo para encapsular una función orientada a objetos, pero tenía que mostrar un ejemplo ...
Usaría la clase final. Me comunica mejor que es una clase auxiliar con algunos métodos de utilidad. Una definición de interfaz es algo que espero que se implemente y los métodos están ahí para ayudar a alguien a implementar la interfaz.
Los métodos estáticos en las interfaces se agregaron con dos propósitos principales:
En caso de implementación deficiente en subclases, los métodos de interfaz estática se pueden usar para proporcionar comprobaciones (por ejemplo, si un valor es nulo).
Evite utilizar clases de utilidad generales (como
Collections
) y llamar a métodos estáticos a través de su interfaz adecuada.
Por lo tanto, es una muy buena práctica si tiene la intención de compartir la funcionalidad con las clases correspondientes.
actualizar:
Si desea construir una colección pura de funciones, entonces puede usar la clase abstracta con métodos estáticos y un constructor privado.