Quiero agregar funcionalidad a la clase java.lang.String
. Pensé en usar el patrón decorador de la siguiente manera:
public class StringDecorator { String str; public StringDecorator(String str) { this.str = str; } // Wrap all methods in String class such as: public int length() { return str.length(); } // Add other methods from String class here.. And then add new functions.. public void newFunction1() { } }
Sin embargo, leí en SO aquí: https://stackoverflow.com/a/3945482 que esto no es apropiado porque String es definitivo y no se puede extender. El usuario también sugiere que "probablemente sea necesario un patrón de diseño diferente".
¿Puede alguien confirmar si de hecho no es apropiado usar el patrón decorador en este escenario y, de ser así, qué otro patrón de diseño se puede usar en su lugar?
Un problema con esto es que en el patrón decorador, el decorador y el objeto que se envuelve generalmente implementan una interfaz común:
interface Interface {...} class A implements Interface {...} class ADecorator implements Interface {...}
De modo que donde un método espera una Interface
, se pueden pasar tanto una A
como un ADecorator
.
Pero en el caso de String
, casi todas las API que lo usan requieren el tipo de implementación String
y no el tipo de interfaz, CharSequence
. Entonces, cuando crea este contenedor, no puede usarlo simplemente con un método que requiere un String
. Y dado que String
es final
, no puede extenderlo y solucionar el problema de esa manera.
Lo que tiene sigue siendo útil, pero debe verse como una composición, y sería útil tener un método getString
(o lo que sea) para recuperar el objeto envuelto (como alguien sugirió), para que aún pueda usarlo con métodos requiriendo una String
.
Suponiendo que también hará que su clase sea inmutable, aún podría ser útil tener esos métodos de delegación, pero en su lugar devolver una instancia de la clase contenedora:
public StringDecorator replace(char oldChar, char newChar) { return new StringDecorator(str.replace(oldChar, newChar)); }
Pero en la mayoría de los casos, podría salirse con la suya con algo como decorator.getString().length()
.