Me encontré con una situación en la que debía extender la funcionalidad de una clase determinada, pero no estoy seguro de la mejor manera de hacerlo. Empecé invocando la funcionalidad "hacia arriba" y ahora he cambiado a "hacia abajo", pero veo problemas con ambos. Déjame explicarte lo que quiero decir. En primer lugar, el enfoque "hacia arriba":¿Cuál es la mejor manera de ampliar la funcionalidad?
public class ParentValidator
{
public void validate() {
// Some code
}
}
public class ChildValidator extends ParentValidator
{
@Override
public void validate() {
super.validate();
// Some code
}
}
public class GrandchildValidator extends ChildValidator
{
@Override
public void validate() {
super.validate();
// Some code
}
}
Esto funciona perfectamente bien, pero requiere que siempre me acuerdo de colocar super.validate() en mi cuerpo método o la lógica de la clase padre (s) ganó' t se ejecutará. Además, la extensión de esta manera puede considerarse "insegura" debido al hecho de que una clase hija podría reemplazar/modificar el código definido en la clase principal. Esto es lo que llamo invocar métodos "hacia arriba" porque estoy invocando métodos de clases de nivel superior a medida que avanzo.
Para contrarrestar estas deficiencias, decidí hacer que ParentValidator.validate() fuera el final y hacer que invoque un método diferente. Esto es lo que mi código se modificó para:
public class ParentValidator
{
public final void validate() {
// Some code
subValidate();
}
protected void subValidate() {}
}
public class ChildValidator extends ParentValidator
{
@Override
public final void subValidate() {
// Some code
subSubValidate();
}
protected void subSubValidate() {}
}
public class GrandchildValidator extends ChildValidator
{
@Override
public void subSubBalidate() {
// Some code
subSubSubValidate();
}
protected void subSubSubValidate();
}
Esto es lo que me refiero cuando digo que estoy llamando a la baja, ya que cada clase invoca métodos en las clases "hacia abajo" la cadena de herencia.
Usando este enfoque, se me puede garantizar que se ejecutará la lógica en la (s) clase (s) primaria (s), lo cual me gusta. Sin embargo, no escala bien. Cuantas más capas de herencia tengo, más fea es. En un nivel, creo que esto es muy elegante. En dos niveles, comienza a parecer de mala calidad. En tres o más, es horrible.
Además, así como tuve que recordar invocar super.validate() como la primera línea de cualquiera de los métodos de validación de mis hijos, ahora debo recordar invocar algún método "subValidar" al final de cualquiera de los métodos de validación de mis padres, por lo que no parecieron mejorar.
Hay una manera mejor de hacer este tipo de extensión que ni siquiera he tocado. Cualquiera de estos enfoques tiene algunos defectos serios y me pregunto si hay un mejor patrón de diseño que podría estar usando.
La única limitación de este enfoque es que debe tener una devolución de llamada en el objeto que se está visitando. Si el objeto está "cerrado", entonces debes resolverlo para reflejarlo (feo). –