sirve settitle que para java design-patterns oop decorator

java - settitle - ¿Pregunta sobre el patrón de decorador y la clase de decorador abstracto?



para que sirve settitle en java (9)

(Un poco tarde a tu pregunta ..)

También pasé bastante tiempo tratando de encontrar una respuesta. En mi caso, el Decorador no concreto extiende la clase para ser decorado ("decoree"), en lugar de una interfaz común tanto para el decoree como para el Decorator.

Después de leer de diferentes fuentes, me parece que, además de lo que dijo tvanfosson , la razón para que los decoradores de concreto extiendan un decorador abstracto o más general es que no repitamos el código de "delegación" una y otra vez .

[Beverage]<———————[(abstract) CondimentDecorator]<—————[Milk] [decoree ]——————<>[ adds code to efficiently ] [ forward calls to decorated ]<—————[LemonJuice] [ instance of Beverage ]

En su caso, su decorador abstracto extendería el decoree e implementaría la misma interfaz que el decoree, delegando / reenviando todas las llamadas de método al mismo. Entonces, los decoradores de hormigón que usted puede construir, solo necesitarían implementar aquellos métodos en los que querría hacer algo diferente que simplemente reenviar la llamada de método al decoree.

Espero haber sido claro ...: -S

Personalmente, estoy un poco decepcionado por la necesidad de repetir la interfaz del decoree en el decorador. Esto agrega algo de acoplamiento, ya que cada vez que la interfaz del decoree cambia (como obtener más métodos), el decorador necesita ponerse al día.

En PHP 5.3.2 (sí, sé que su pregunta está relacionada con Java), sin embargo, debería ser posible capturar dinámicamente todas las llamadas de métodos y reenviarlas todas, sin que el Decorador necesite saber qué métodos se están llamando (en un no una forma muy eficiente, sin embargo, teniendo que utilizar la API de Reflection). Supongo que esto es posible en Ruby y otros idiomas ya.

PD: ¡Esta es mi primera respuesta en SO! ^ _ ^

Esta pregunta ya tiene una respuesta aquí:

Esta pregunta ya se hizo here , pero en lugar de responder a la pregunta específica, en su lugar se dieron descripciones de cómo funciona el patrón decorador. Me gustaría preguntárselo nuevamente porque la respuesta no es inmediatamente evidente para mí simplemente leyendo cómo funciona el patrón decorador (he leído el artículo de wikipedia y la sección del libro Head First Design Patterns).

Básicamente, quiero saber por qué se debe crear una clase decoradora abstracta que implemente (o amplíe) alguna interfaz (o clase abstracta). ¿Por qué no pueden todas las nuevas "clases decoradas" simplemente implementar (o extender) el objeto abstracto base (en lugar de extender la clase decoradora abstracta)?

Para hacer esto más concreto, usaré el ejemplo del libro de patrones de diseño que trata con bebidas de café:

  • Hay una clase de componente abstracta llamada Beverage
  • Tipos de bebidas simples como HouseBlend simplemente extienden Beverage
  • Para decorar bebidas, se crea una clase abstracta CondimentDecorator que extiende Beverage y tiene una instancia de Beverage
  • Digamos que queremos agregar un condimento de "leche", se crea una clase de Milk que extiende CondimentDecorator

Me gustaría entender por qué necesitábamos la clase CondimentDecorator y por qué la clase Milk no podría haber extendido la clase Beverage sí misma y se le ha pasado una instancia de Beverage en su constructor.

Esperemos que esto quede claro ... si no , simplemente me gustaría saber por qué es necesaria la clase de decorador abstracto para este patrón . Gracias.

Edit: traté de implementar esto, omitiendo la clase de decorador abstracto, y parece que todavía funciona. ¿Esta clase abstracta está presente en todas las descripciones de este patrón simplemente porque proporciona una interfaz estándar para todas las nuevas clases decoradas?


El decorador base hace que sea más fácil crear decoradores adicionales. Imagine que Bebidas tiene docenas de métodos abstractos, o es una interfaz, por ejemplo, stir (), getTemperature (), drink (), pour () y similares. Luego, todos sus decoradores tienen que implementar estos métodos por ninguna otra razón que delegarlos a la bebida envuelta, y su MilkyBeverage y SpicyBeverage tienen todos esos métodos.

Si, en cambio, tiene una clase de BeverageDecorator concreta que extiende o implementa Beverage simplemente delegando cada llamada a la Beverage envuelta, las subclases pueden extender BeverageDecorator y solo implementar los métodos que les interesan, dejando la clase base para manejar la delegación.

Esto también lo protege si la clase de Bebidas (o interfaz) alguna vez obtiene un nuevo método abstracto: todo lo que necesita hacer es agregar el método a la clase BeverageDecorator. Sin él, tendría que agregar ese método a todos y cada uno de los Decoradores que haya creado.


En el caso del patrón Decorator, la herencia se utiliza para la coincidencia de tipos. Esta no es la razón típica para la subclasificación. La razón normal para la subclasificación es heredar el comportamiento

Para dejar clara esta distinción, tiene sentido sub-clasificar Bebidas con CondimentDecorator porque la clase CondimentDecorator hace que la distinción entre una implementación de bebida (como DarkRoast) y un condimento (como Mocha) sea clara. Considere, por ejemplo, que recibió la tarea de crear un menú para StarBuzz solo con mirar el código. Inmediatamente sabrá cuáles son las bebidas "de base" y qué condimentos si se considera la clase base. La clase base de DarkRoast es Beverage. La clase base de Mocha es CondimentDecorator.

Sin embargo, creo que podría tener más sentido en Java implementar la clase abstracta Beverage como una interfaz. Según el libro, el código no usó este enfoque porque StarBuzz ya tenía una clase de Bebida abstracta (p 93) y un componente base abstracto es el enfoque histórico para implementar el patrón.


La clase BaseDecorator (CondimentDecorator) obliga a ConcreteDecortor (Milk) a tener una clase de base (Brevrage) en el constructor.

Si la clase BaseDecorator no existe, no te obliga a implementar un decorador que requiera una BaseAbstractClass en la entrada. El objetivo del Patrón de decorador es hacer cumplir la entrada y salida de clases.

(Creo que toma su ejemplo de Head First Design Pattern, y en su ejemplo, la clase BaseDecorator no tiene este contructor).


Me preguntaba lo mismo. Volviendo a la fuente, los patrones de diseño de GOF, veo esto en "Implementación" en el capítulo de Decorator:

"Omitir la clase de Decorador abstracto. No es necesario definir una clase de Decorador abstracto cuando solo necesita agregar una responsabilidad. Ese es a menudo el caso cuando se trata de una jerarquía de clases existente en lugar de diseñar una nueva. En ese caso, puede combinar la responsabilidad de Decorator para reenviar las solicitudes al componente al Concrete Decorator ".

Así que al menos en ese caso, parece que GOF está de acuerdo contigo :-)

No estoy seguro de cuál es el significado de ''una responsabilidad''. No estoy seguro de si más de ''una responsabilidad'' significaría un decorador concreto que tiene más de una responsabilidad o más de un decorador concreto, cada uno con su única responsabilidad. De cualquier manera, no veo por qué el Decorador abstracto es necesario. Supongo que la respuesta de Tvanfosson (en su comentario sobre su propia respuesta) es la correcta: que una vez que comienza a crear varias clases de decoración, aclara la decisión de diseño de agruparlas en una superclase. Por otro lado, donde solo hay una clase, tal vez haga que la decisión de diseño sea menos clara si agrega una segunda clase que solo se sienta como un intermediario sin sentido entre el componente base y el decorador (habiendo dicho eso, es bastante probable que querrá agregar más en algún momento, así que tal vez sea mejor incluir el decorador abstracto incluso en el caso individual ...)

En cualquier caso, parece que tiene que ver con aclarar el diseño, en lugar de ser la diferencia entre el código que funciona y el que no.


Mejor un año y medio tarde que nunca:

No es necesaria una clase base para decoradores de cierta interfaz, pero es muy útil tenerla.

Es útil, por un lado, como un medio para documentar que las clases derivadas de él son los decoradores de la interfaz en cuestión, pero sobre todo porque los decoradores generalmente no necesitan agregar funcionalidad a cada método de la interfaz decorada, por lo que una clase decoradora de base permite a los decoradores derivados implementar solo aquellos métodos de la interfaz a los que realmente necesitan agregar alguna funcionalidad, dejando el resto de los métodos a la clase base para proporcionar una implementación predeterminada para. (Que simplemente delega la llamada al decoree).

Contrasta esto con los decoradores de escritura que implementan la interfaz decorada desde cero, donde el compilador requiere que proporcione una implementación para cada método único de la interfaz, ya sea que su decorador le agregue alguna funcionalidad o no.

Es así de simple, de verdad.


Permite la decoración de la clase base de forma independiente con varios decoradores en diferentes combinaciones sin tener que derivar una clase para cada combinación posible. Por ejemplo, digamos que quieres tu Beverage con leche y nuez moscada. Usando decoradores basados ​​en la clase de decoradores abstractos, simplemente envuelve con decoradores de Milk y Nutmeg . Si se derivara de Beverage , tendría que tener una clase de MilkWithNutmegBeverage y una clase de MilkBeverage y una clase de NutmegBeverage . Puedes imaginarte cómo explota esto a medida que aumenta el número de combinaciones posibles. El uso de la implementación del decorador abstracto reduce esto a solo una implementación de clase de decorador por decoración.


de hecho, a veces también omito esta abstracción del "hombre medio" (si no tienes muchas combinaciones de decoradores). se desacopla más pero también agrega complejidad. en mi opinión, la idea principal detrás de la decoración es envolver interfaces dentro de sus propias implementaciones.


tal vez años demasiado tarde, pero aquí está el punto con la declaración gof de responsabilidad única.

Supongamos que el decorador abstracto también tiene métodos adicionales que no son propios del componente (abstracto), y que el decarador tiene múltiples responsabilidades.

esto garantiza que el componente siempre sea reutilizable, ya que debe implementar todo el resumen / interfaz del componente, pero no debe implementar la responsabilidad adicional del decorador.

cualquier programa que use el componente (resumen) puede garantizar que el componente funcione en consecuencia en el uso (en ejecución) y concretar la creación del componente (resumen). por lo tanto, esto garantizará la integridad del programa y la facilidad de desarrollo y la expansión de la aplicación / programa.

por lo tanto, el decorador dejará a aquellos que aman y luego como si fueran su propio objeto para usarlo de cualquier manera posible, incluyen modales similares a los anteriores. p.ej. decorador siendo decorado. (solo una idea)

genial, ¿no? (aplaudir)