El patrón decorador Diseño
-
21-08-2019 - |
Pregunta
Estoy empezando a aprender los patrones de diseño y tengo dos preguntas relacionadas con el decorador ...
Me preguntaba por qué el patrón decorador sugiere que el decorador de poner en práctica todos los métodos públicos del componente de la que decora?
No se puede simplemente la clase decorador ser utilizado para proporcionar los comportamientos adicionales, y entonces el componente de hormigón (que se pasa en ella) solo se utiliza para llamar a todo lo demás?
Y en segundo lugar, ¿y si el componente de hormigón que desea decorar no tiene una clase base que el decorador abstracto también puede derivar de?
Gracias de antemano!
Solución
Creo que tienes haber entendido mal decorador. Usted está pensando en un caso simple de extender una clase concreta con la funcionalidad adicional. En este caso, sí en la mayoría de lenguajes orientados a la clase derivada puede simplemente permitir que su superclase para manejar cualquiera de los métodos no implementados.
class Base {
function foo() {
return "foo";
}
function bar() {
return "bar";
}
}
// Not what we think of as a Decorator,
// really just a subclass.
class Decorator extends Base {
// foo() inherits behavior from parent Base class
function bar() {
return parent::bar() . "!"; // add something
}
}
Una clase decorador no extender la clase base de su clase "decorado". Es un tipo diferente, que tiene un objeto de miembro de la clase decorado. Por lo tanto, debe implementar la misma interfaz, aunque sólo sea para llamar al método respectivo del objeto decorado.
class Decorator { // extends nothing
protected $base;
function __construct(Base $base) {
$this->base = $base;
}
function foo() {
return $base->foo();
}
function bar() {
return $base->foo() . "!"; // add something
}
}
Podría ser útil para definir un Interfaz (si es compatible con su idioma tal cosa) tanto para la clase decorada y la clase decorador. De esta manera se puede comprobar en tiempo de compilación que el decorador implementa la misma interfaz.
interface IBase {
function foo();
function bar();
}
class Base implements IBase {
. . .
}
class Decorator implements IBase {
. . .
}
Re: comentario de @Yossi Dahan: Veo la ambigüedad en el artículo de Wikipedia, pero si usted lee cuidadosamente sí dice que el componente que se está decorada es un campo en el objeto decorador, y que el componente se pasa como argumento al constructor decorador. Esto es diferente de la herencia.
Aunque el artículo de wikipedia Qué dice la decoradora hereda del componente, se debe pensar en esto como la implementación de una interfaz, como he mostrado en el ejemplo anterior de PHP. El decorador todavía tiene que proxy para el objeto componente, lo que sería si no había heredado. Esto permite que el decorador para decorar un objeto de cualquier clase que implementa la interfaz.
Estos son algunos extractos de "Patrones de diseño: Elementos de software reutilizables orientada a objetos" de Gamma, Helm, Johnson y Vlissides:
decorador
Intención
Adjuntar responsabilidades adicionales a un objeto dinamicamente. Decoradores proporcionan una alternativa flexible a la subclasificación para extender la funcionalidad.
Motivation
... Un decorador se ajusta a la interfaz de el componente que decora de manera que su presencia es transparente para el Los clientes de componentes.
Participantes
- Decorador mantiene una referencia a un objeto de componentes y define una interfaz que se ajusta a la interfaz del componente.
Otros consejos
Me preguntaba por qué el patrón decorador sugiere que el decorador de poner en práctica todos los métodos públicos del componente de la que decora?
Un decorador debe ser una gota en el reemplazo para el componente que decora, con funcionalidad adicional (la "decoración"). Esto sólo puede ocurrir si se implementa por completo la interfaz del componente.
No se puede simplemente la clase decorador ser utilizado para proporcionar los comportamientos adicionales, y entonces el componente de hormigón (que se pasa en ella) solo se utiliza para llamar a todo lo demás?
Eso hace suposiciones sobre cómo se implementa el decorador. No se puede estar seguro de que toda la interfaz pública del componente que decora se está pasando a través directamente. Es posible que el decorador anula ciertos métodos en su aplicación.
Y en segundo lugar, ¿y si el componente de hormigón que desea decorar no tiene una clase base que el decorador abstracto también puede derivar de?
Decoradores generalmente heredan de clase del componente que están decorando, no la base del componente.