Principios de diseño de patrones de diseño

¿Por qué defender los "patrones de diseño"? La razón fundamental es reutilizar el código y aumentar la mantenibilidad. Entonces, ¿cómo podemos lograr la reutilización del código? Hay varios principios de orientación a objetos: principio de responsabilidad única (principio abierto y cerrado), principio de sustitución de Richter (principio de sustitución de Liskov, LSP), principio de inversión de dependencia (DIP), principio de aislamiento de interfaz (ISP), principio de reutilización compuesta/agregación ( CARP), Principio del Mínimo Conocimiento (PLK). El principio de apertura y cierre tiene un color de idealismo, que es el objetivo final del diseño orientado a objetos. Otros elementos pueden considerarse métodos de implementación del principio de apertura y cierre.

Los patrones de diseño están diseñados para implementar estos principios para lograr la reutilización del código y aumentar la mantenibilidad. Este principio fue propuesto por Bertrand Meyer. El texto original es: "Las entidades de software deben estar abiertas a la extensión, pero cerradas a la modificación". Es decir, los módulos deben estar abiertos para ampliación y cerrados para modificación. Este módulo debe ampliarse sin modificar el código original. Entonces, ¿cómo expandirse? Veamos el modelo de fábrica: supongamos que hay un niño en Zhongguancun que vende CD pirateados y películas pornográficas. Diseñamos un software de gestión de ventas de CD para él. Primero deberíamos diseñar una interfaz de "CD". Como se muestra en la imagen:

[Anterior]

______________

| & lt& gt|

| CD |

|_____________|

|+Vender () |

| |

|_____________|

[/pre]< / p>

CDs pirateados y pornografía son sus subcategorías. Kid gestiona estos CD a través de "DiscFactory". Nombre en clave: ¿Público? ¿clase? DiscFactory{público? ¿Electricidad estática? obtener disco (nombre de cadena) { clase de retorno (disco). nombre(nombre). newstance();}} Alguien quiere comprar un disco pirateado, ¿qué debe hacer? ¿público? ¿clase? Niño {público? ¿Electricidad estática? ¿Vacío? principal(Cadena[]?Args){ CD? ¿d? =?DiscFactory.getDisc(disco pirateado); d. sell();}} Si un día, este niño se da cuenta de su conciencia y comienza a vender software genuino. No importa, solo necesitamos crear una subcategoría de "CD" y "Software original" sin modificar la estructura y el código originales. ¿cómo son las cosas? Abierto a la extensión, cerrado a la modificación: el "principio de abierto-cerrado".

El patrón de fábrica es ampliar productos específicos, y algunos proyectos pueden requerir más extensiones. Si ampliáramos esta "fábrica", se convertiría en una "fábrica abstracta". El principio de reutilización de compuestos/agregación (CARP) a menudo se denomina principio de reutilización de compuestos. El principio de reutilización de combinación/agregación es utilizar algunos objetos existentes en un nuevo objeto para hacerlos parte del nuevo objeto; el nuevo objeto logra el propósito de reutilizar funciones existentes delegando a estos objetos. Su principio de diseño es: utilizar la composición/agregación tanto como sea posible y evitar la herencia tanto como sea posible.

En otras palabras, utilizar menos herencia y más uso de relaciones compuestas. Una vez escribí un programa como este: hay varias clases que necesitan manejar la base de datos, así que escribí una clase que opera la base de datos, y luego todas las demás clases que manejan la base de datos heredan esto. Como resultado, más tarde modifiqué el método de una clase de operación de base de datos y fue necesario modificar todas las clases. "¡Un movimiento afecta a todo el cuerpo"! Orientado a objetos consiste en limitar las fluctuaciones al rango más pequeño posible.

En Java, deberías intentar programar para interfaces, no para clases de implementación. De esta forma, reemplazar una subclase no afecta el código que llama a sus métodos. Deje que cada clase tenga el menor contacto posible con los demás y "no hable con extraños". De esta forma, el incendio en la puerta de la ciudad no dañará a los peces del estanque. Puede mejorar la escalabilidad y la mantenibilidad. Hay tres tipos de patrones de diseño, ***23. Modos creativos: Modo Singleton, Fábrica abstracta, Modo Constructor, Modo Fábrica, Modo Prototipo. Patrones estructurales: modo adaptador, modo puente, modo decoración, modo composición, modo apariencia, modo disfrute y modo proxy. Patrones de comportamiento: patrón de método de plantilla, patrón de comando, patrón de iterador, patrón de observador, patrón de mediador, patrón de nota, patrón de intérprete, patrón de estado, patrón de estrategia, patrón de cadena de responsabilidad, patrón de visitante. Una breve introducción en el orden del diccionario es la siguiente.

Abstract Factory: Proporciona una interfaz para crear una serie de objetos relacionados o interdependientes sin especificar sus clases específicas.

Modo Adaptador: Convierte la interfaz de una clase en otra interfaz que el cliente desee. El patrón Adaptador permite trabajar juntas clases que no pueden hacerlo debido a interfaces incompatibles.

Puente: Separa la parte abstracta de su implementación para que ambas puedan cambiarse de forma independiente.

Builder (modo constructor): Separa la construcción de un objeto complejo de su representación, de modo que un mismo proceso de construcción puede crear diferentes representaciones.

Cadena de responsabilidad: separe el remitente y el destinatario de una solicitud para que varios objetos tengan la oportunidad de manejar la solicitud. Conecte estos objetos en una cadena y pase la solicitud a lo largo de la cadena hasta que un objeto la maneje.

Modo de comando: encapsule una solicitud en un objeto para que pueda parametrizar diferentes solicitudes de los clientes; poner en cola o registrar solicitudes y admitir operaciones cancelables.

Modo compuesto: combina objetos en una estructura de árbol para representar una jerarquía "parte-todo". Permite a los clientes utilizar objetos individuales y objetos compuestos de forma coherente.

Modo de decoración: agrega dinámicamente algunas responsabilidades adicionales a un objeto. En lo que respecta a las funciones de extensión, son más flexibles que las subclases.

Fachada: Proporciona una interfaz consistente para un conjunto de interfaces en un subsistema. El patrón Facade define una interfaz de alto nivel para hacer que este subsistema sea más fácil de usar.

Método de fábrica: define una interfaz para crear objetos y deja que las subclases decidan qué clase crear una instancia. Los métodos de fábrica difieren la creación de instancias de una clase a sus subclases.

Flyweight (modo meta Enjoy): utilice la tecnología * * * enjoy para soportar eficazmente una gran cantidad de objetos de grano fino.

Intérprete (modo analizador): dado un idioma, define una representación de su gramática y define un intérprete que usa la representación para interpretar oraciones en el idioma.

Iterador (patrón Iterador): proporciona una forma de acceder secuencialmente a los elementos de un objeto agregado sin exponer la representación interna del objeto.

Mediación (modo de mediación): Los objetos de mediación se utilizan para encapsular una serie de interacciones de objetos. La mediación elimina la necesidad de que los objetos se refieran explícitamente entre sí, lo que afloja su acoplamiento y cambia sus interacciones de forma independiente.

Modo recuerdo: captura el estado interno del objeto y lo guarda fuera del objeto sin destruir la encapsulación. De esta manera, el objeto se puede restaurar a su estado guardado más adelante.

Patrón de observador: define una relación de dependencia de uno a muchos entre objetos, de modo que cuando el estado de un objeto cambia, todos los objetos que dependen de él serán notificados y actualizados automáticamente.

Prototipo (modo prototipo): especifique el tipo de objeto que se creará utilizando una instancia de prototipo y cree un nuevo objeto copiando este prototipo.

Proxy (modo proxy): proporciona un proxy para que otros objetos controlen el acceso al objeto.

Patrón Singleton: Garantiza que una clase tenga solo una instancia y proporciona un punto de acceso global para acceder a ella. El patrón Singleton es uno de los patrones de diseño más simples, pero tiene muchos inconvenientes para los desarrolladores de Java. En su columna de septiembre, David Geary analizó el patrón singleton y cómo abordar sus dificultades frente a los subprocesos múltiples, los cargadores de clases y la serialización.

Patrón de estado: permite que un objeto cambie su comportamiento cuando cambia su estado interno. El objeto parece haber modificado la clase a la que pertenece.

Estrategia: Definir una serie de algoritmos y encapsularlos uno por uno para hacerlos reemplazables. Este modelo permite que el algoritmo cambie independientemente de los clientes que lo utilicen.

Método de plantilla: define el esqueleto de un algoritmo en funcionamiento y difiere algunos pasos a subclases. Los métodos de plantilla permiten a las subclases redefinir ciertos pasos de un algoritmo sin cambiar su estructura.

Patrón de visitante: representa operaciones que actúan sobre cada elemento de la estructura del objeto. Le permite definir nuevas operaciones sobre elementos sin cambiar sus clases.

A partir de la siguiente sección, se describe en detalle cada uno de los siguientes patrones de diseño. Propósito

Definir una interfaz para crear objetos y dejar que las subclases decidan qué clase crear una instancia. Los métodos de fábrica difieren la creación de instancias de una clase a sus subclases.

La aplicabilidad ocurre cuando una clase no conoce la clase del objeto que debe crear. Cuando una clase quiere que sus subclases especifiquen los objetos que crea. Cuando una clase delega la responsabilidad de crear un objeto a una de varias subclases auxiliares y desea localizar la información sobre qué subclase auxiliar es la delegada. Propósito

Proporciona una interfaz para crear una serie de objetos relacionados o interdependientes sin especificar sus clases específicas.

Idoneidad Un sistema debe ser independiente de la creación, montaje y presentación de sus productos. Cuando el sistema está configurado con una de varias familias de productos. Cuando se desea resaltar el diseño de una serie de objetos de producto relacionados para uso común. Cuando proporciona una biblioteca de clases de productos, solo desea mostrar sus interfaces en lugar de sus implementaciones. Finalidad

Separar la construcción de un objeto complejo de su representación, de modo que un mismo proceso de construcción pueda crear diferentes representaciones.

La aplicabilidad cuando los algoritmos utilizados para crear objetos complejos deben ser independientes de los componentes del objeto y de cómo están ensamblados. Cuando el proceso constructivo debe permitir diferentes representaciones del objeto construido. Propósito

Especificar los tipos de objetos que se crearán utilizando instancias de prototipos y crear nuevos objetos copiando estos prototipos.

Aplicabilidad cuando la clase a instanciar se especifica en tiempo de ejecución, por ejemplo, mediante carga dinámica o para evitar la creación de una jerarquía de clases de fábrica paralela a la jerarquía de clases de producto o cuando las instancias de una clase solo son Can; tener una de varias combinaciones de estado diferentes. Puede ser más conveniente construir una cantidad correspondiente de prototipos y clonarlos que crear manualmente una instancia de la clase con el estado apropiado cada vez. Propósito

Asegurar que una clase tenga solo una instancia y proporcionar un punto de acceso global para acceder a ella.

Aplicabilidad cuando una clase puede tener sólo una instancia y los clientes pueden acceder a ella desde un punto de acceso conocido. Cuando esta instancia única debería ser extensible mediante subclases, los clientes deberían poder usar la instancia extendida sin cambiar su código. Propósito

Convertir la interfaz de una clase en otra interfaz que el cliente desee. El patrón Adaptador permite trabajar juntas clases que no pueden hacerlo debido a interfaces incompatibles.

Aplicabilidad Quiere utilizar una clase existente, pero su interfaz no satisface sus necesidades. Desea crear una clase reutilizable que pueda funcionar con otras clases no relacionadas o clases impredecibles (es decir, clases cuyas interfaces pueden ser incompatibles). (Solo adaptadores de objetos) Desea utilizar algunas subclases existentes, pero no es posible subclasificar cada una para que coincida con su interfaz. Los adaptadores de objetos pueden adaptar la interfaz de su clase principal. Finalidad

Separar la parte abstracta de su implementación para que ambas puedan modificarse de forma independiente.

Aplicabilidad No deseas un vínculo fijo entre una abstracción y su implementación. Por ejemplo, esto podría deberse a que las partes de la implementación deberían poder seleccionarse o cambiarse mientras el programa se está ejecutando. La abstracción de una clase y su implementación debe ampliarse generando subclases. En este punto, el patrón Bridge le permite combinar diferentes interfaces abstractas y partes de implementación y extenderlas por separado. Las modificaciones a la parte de implementación abstracta no deberían tener ningún impacto en los clientes, es decir, no es necesario volver a compilar el código de los clientes. (C++) Quiere ocultar completamente la parte de implementación abstracta a los clientes. En C++, la representación de una clase es visible en la interfaz de clase. Hay muchas clases para generar. Tal jerarquía de clases significa que hay que dividir un objeto en dos partes. Rumbaugh llama a esta jerarquía de clases "generalización anidada". Desea * * * compartir la implementación entre múltiples objetos (posiblemente usando el recuento de referencias), pero al mismo tiempo pedirle al cliente que no lo sepa. Un ejemplo simple es la clase String de Coplien, donde múltiples objetos pueden * * * disfrutar de la misma representación de cadena (StringRep). Propósito

Agrupar objetos en una estructura de árbol para representar una jerarquía "parte-todo". c, O, P, O, S, I, T, E permiten a los usuarios trabajar con objetos individuales y combinados de manera consistente.

Aplicabilidad Desea representar una parte de un objeto: la jerarquía general. Quiere que el usuario ignore la diferencia entre un objeto compuesto y un objeto único y, en su lugar, utilice todos los objetos de la estructura compuesta de manera uniforme. Propósito

Agregar dinámicamente algunas responsabilidades adicionales a un objeto. El patrón decorador es más flexible que las subclases cuando se trata de agregar funciones.

La aplicabilidad agrega responsabilidades de forma dinámica y transparente a objetos individuales sin afectar a otros objetos. Atender aquellas responsabilidades que sean revocables. Cuando no puedes extenderlo mediante subclases.

En un caso, puede haber una gran cantidad de extensiones independientes y se generará una gran cantidad de subclases para admitir cada combinación, lo que hará que la cantidad de subclases se dispare. Otra situación puede deberse a que la definición de clase está oculta o la definición de clase no se puede utilizar para generar subclases. Propósito

Proporcionar una interfaz consistente para un conjunto de interfaces en un subsistema. El patrón Facade define una interfaz de alto nivel, lo que hace que el subsistema sea más fácil de usar.

Aplicabilidad Cuando se desea proporcionar una interfaz sencilla a un subsistema complejo. Los subsistemas suelen volverse cada vez más complejos a medida que evolucionan. La mayoría de los patrones producen más clases y más pequeñas cuando se usan. Esto hace que el subsistema sea más reutilizable y más fácil de personalizar, pero también crea algunas dificultades para los usuarios que no necesitan personalizar el subsistema. Fachada puede proporcionar una vista predeterminada simple que es suficiente para la mayoría de los usuarios, mientras que aquellos que requieren más personalización pueden mirar más allá de la capa Fachada. Existe una gran dependencia entre el programa cliente y la parte de implementación de la clase abstracta. La introducción de Facade separa este subsistema de los clientes y otros subsistemas, lo que puede mejorar la independencia y portabilidad del subsistema. Cuando necesite construir un subsistema en capas, utilice el patrón de fachada para definir los puntos de entrada para cada capa en el subsistema. Si los subsistemas son interdependientes, puede simplificar las dependencias entre ellos haciendo que se comuniquen sólo a través de la fachada. Propósito

Utilizar * * * tecnología enjoy para admitir de manera efectiva una gran cantidad de objetos de grano fino.

Las aplicaciones utilizan una gran cantidad de objetos. Debido al uso de una gran cantidad de objetos, se incurre en una gran sobrecarga de almacenamiento. La mayoría de los estados de un objeto se pueden cambiar a estados externos. Si elimina el estado externo de un objeto, puede reemplazar muchos grupos de objetos con relativamente pocos objetos. La aplicación no se basa en el reconocimiento de objetos. Debido a que los objetos Flyweight pueden ser * * *, las pruebas de reconocimiento devolverán verdadero para objetos conceptualmente distintos. Propósito

Proporciona un proxy para que otros objetos controlen el acceso a este objeto.

Adaptabilidad

Utilice el patrón proxy cuando necesite reemplazar un puntero simple con un puntero de objeto más general y complejo. A continuación se muestran algunas situaciones comunes en las que se puede utilizar el modo proxy: Un proxy remoto proporciona una representación local de un objeto en un espacio de direcciones diferente. Los agentes virtuales crean objetos costosos según sea necesario. El agente de protección controla el acceso al objeto original. Los proxies de protección se utilizan cuando los objetos deben tener diferentes derechos de acceso. Las referencias inteligentes reemplazan los punteros simples, que realizan algunas operaciones adicionales al acceder a un objeto. Sus usos típicos incluyen: contar referencias a objetos reales para que cuando ya no se haga referencia al objeto, se pueda liberar automáticamente (también conocido como SmartPointers). Cuando se hace referencia a un objeto persistente por primera vez, se carga en la memoria. Antes de acceder al objeto real, verifique que esté bloqueado para asegurarse de que otros objetos no puedan cambiarlo. Propósito

Permitir que múltiples objetos tengan la oportunidad de procesar solicitudes, evitando así la relación de acoplamiento entre el remitente y el receptor de la solicitud. Conecte estos objetos en una cadena y pase la solicitud a lo largo de la cadena hasta que un objeto la maneje.

Aplicabilidad Varios objetos pueden manejar una solicitud y el tiempo de ejecución en el que el objeto maneja la solicitud se determina automáticamente. Quiere enviar una solicitud a uno de varios objetos sin especificar explícitamente el destinatario. El conjunto de objetos que pueden manejar la solicitud debe especificarse dinámicamente. Propósito

Encapsular una solicitud en un objeto para que los clientes con diferentes solicitudes puedan parametrizarse en cola o registrar solicitudes y admitir operaciones cancelables.

La aplicabilidad es la misma que la del objeto MenuItem discutido anteriormente, abstrayendo las operaciones a realizar para parametrizar el objeto. Este mecanismo de parametrización se puede expresar mediante funciones de devolución de llamada en un lenguaje procedimental. La llamada función de devolución de llamada consiste en registrar la función en algún lugar primero y luego llamarla cuando sea necesario más adelante. El patrón de comando es una alternativa orientada a objetos al mecanismo de devolución de llamada. Especificar, programar y ejecutar solicitudes en diferentes momentos. La vida útil del objeto de comando puede ser independiente de la solicitud inicial. Si el destinatario de la solicitud se puede expresar de manera independiente del espacio de direcciones, el objeto de comando responsable de la solicitud se puede transferir a un proceso diferente y la solicitud se puede implementar allí. Se admite la operación de cancelación. La operación Ejecutar del comando puede almacenar el estado antes de que se implemente la operación y utilizar este estado para eliminar el impacto de la operación cuando se cancela. Se debe agregar una acción de ejecución a la interfaz de comando, que cancelará los efectos de la última llamada de ejecución.

Los comandos ejecutados se almacenan en la lista del historial. Al recorrer esta lista de un lado a otro y llamar a UnExecute y Execute respectivamente, puede "cancelar" y "rehacer" sin límite. Admite el registro de cambios para que los cambios se puedan rehacer si el sistema falla. Se puede agregar operaciones de carga y operaciones de almacenamiento a la interfaz de comando para mantener un registro de cambios consistente. El proceso de recuperación de un fallo implica volver a leer los comandos grabados en el disco y volver a ejecutarlos mediante la operación de ejecución. Construya un sistema con operaciones de alto nivel que se basen en operaciones primitivas. Esta estructura es común en los sistemas de información que soportan transacciones. Una transacción encapsula un conjunto de cambios en los datos. El patrón de comando proporciona una forma de modelar transacciones. Los comandos tienen una interfaz pública para que puedas llamar a todas las transacciones de la misma manera. Al mismo tiempo, es fácil agregar nuevas transacciones para ampliar el sistema utilizando este modelo. Propósito

Dado un idioma, definir una representación de su gramática y definir un intérprete que use la representación para interpretar oraciones en el idioma.

Aplicabilidad Cuando hay un lenguaje que necesita ser interpretado y ejecutado, y puedes representar las oraciones en el lenguaje como un árbol de sintaxis abstracta, puedes usar el modo intérprete. Este modelo funciona mejor cuando la gramática es simple y la jerarquía de clases de la gramática se vuelve grande e inmanejable para gramáticas complejas. Aquí es cuando una herramienta como Parser Generator es una mejor opción. Pueden interpretar expresiones sin crear árboles de sintaxis abstracta, lo que ahorra espacio y tiempo. La eficiencia no es la cuestión clave. Los intérpretes más eficientes normalmente no hacen esto interpretando árboles de análisis sintáctico directamente, sino convirtiéndolos primero a otra forma. Por ejemplo, las expresiones regulares suelen convertirse en máquinas de estados. Pero incluso en este caso, el convertidor aún se puede implementar en modo intérprete, lo que aún puede resultar útil. Propósito

Proporcionar una forma de acceder secuencialmente a los elementos de un objeto agregado sin exponer la representación interna del objeto.

La aplicabilidad accede al contenido de un objeto agregado sin exponer su representación interna. Admite múltiples recorridos de objetos agregados. Proporciona una interfaz unificada para atravesar diferentes estructuras agregadas (es decir, admite iteración polimórfica). Propósito

Utilizar objetos intermediarios para encapsular una serie de interacciones de objetos. La mediación elimina la necesidad de que los objetos se refieran explícitamente entre sí, lo que afloja su acoplamiento y cambia sus interacciones de forma independiente.

Aplicabilidad Un conjunto de objetos se comunican de forma bien definida pero compleja. La interdependencia resultante es confusa y difícil de entender. Un objeto hace referencia a muchos otros objetos y se comunica directamente con ellos, lo que dificulta la reutilización del objeto. Quiero personalizar un comportamiento que se distribuye en varias clases, pero no quiero generar demasiadas subclases. Propósito

Capturar el estado interno del objeto y guardarlo fuera del objeto sin romper la encapsulación. De esta manera, el objeto se puede restaurar a su estado guardado más adelante.

La aplicabilidad debe preservar (parte de) el estado de un objeto en un momento determinado para que pueda restaurarse a un estado anterior si es necesario más adelante. Si uno usa una interfaz para permitir que otros objetos obtengan estos estados directamente, expone los detalles de implementación del objeto y rompe la encapsulación del objeto. Propósito

Definir dependencias de uno a muchos entre objetos. Cuando el estado de un objeto cambia, todos los objetos que dependen de él reciben una notificación y se actualizan automáticamente.

Aplicabilidad cuando un modelo abstracto tiene dos aspectos, uno de los cuales depende del otro. Encapsule ambos en objetos separados para que puedan cambiarse y reutilizarse de forma independiente. Cuando un cambio en un objeto requiere cambios en otros objetos al mismo tiempo, no sé cuántos objetos deben cambiarse. Cuando un objeto debe notificar a otros objetos, no puede asumir quiénes son los otros objetos. En otras palabras, no desea que estos objetos estén estrechamente acoplados. Propósito

Permite que un objeto cambie su comportamiento cuando cambia su estado interno. El objeto parece haber modificado su clase.

Aplicabilidad El comportamiento de un objeto depende de su estado y debe cambiar su comportamiento en función del estado en tiempo de ejecución. Una operación consta de una enorme declaración condicional de múltiples ramas que depende del estado del objeto. Este estado suele estar representado por una o más constantes de enumeración. A menudo, existen varias operaciones que contienen la misma estructura condicional. El patrón de estado coloca cada rama condicional en una clase separada. Esto le permite considerar el estado de un objeto como un objeto de acuerdo con su propia situación. Este objeto puede cambiar de forma independiente y no depende de otros objetos. Propósito

Definir una serie de algoritmos y encapsularlos uno por uno para hacerlos reemplazables.

Este modelo permite que el algoritmo cambie independientemente de los clientes que lo utilicen.

Aplicabilidad Muchas clases relacionadas simplemente se comportan de manera diferente. Las estrategias proporcionan una manera de configurar una clase con uno de varios comportamientos. Es necesario utilizar diferentes variaciones del algoritmo. Por ejemplo, puede definir algunos algoritmos que reflejen diferentes compensaciones de espacio/tiempo. El patrón Estrategia se puede utilizar cuando estas variaciones se implementan como una jerarquía de clases de algoritmos. Los algoritmos utilizan datos que se supone que los clientes no deben conocer. El patrón de estrategia se puede utilizar para evitar exponer estructuras de datos complejas relacionadas con algoritmos. Una clase define una variedad de comportamientos, que aparecen en forma de múltiples declaraciones condicionales en las operaciones de esta clase. Reemplace estas declaraciones condicionales moviendo las ramas condicionales relevantes a sus respectivas clases de políticas. Propósito

Definir el esqueleto de un algoritmo en operaciones y diferir algunos pasos a subclases. La plantilla permite a las subclases redefinir ciertos pasos de un algoritmo sin cambiar su estructura.

La aplicabilidad implementa las partes inmutables de un algoritmo a la vez, dejando el comportamiento modificable a las subclases. El comportamiento del hombre en cada subclase debe extraerse y concentrarse en una clase principal masculina para evitar la duplicación de código. Éste es un buen ejemplo de lo que Opdyke y Johnson describen como "descomposición en generalización". Primero, identifique las diferencias en el código existente y separe las diferencias en nuevas operaciones. Finalmente, reemplace este código diferente con métodos de plantilla que llamen a estas nuevas operaciones. Controlar la extensión de la subclase. Los métodos de plantilla solo llaman a operaciones de "gancho" en puntos específicos, permitiendo la expansión solo en esos puntos. Propósito

Representa operaciones que actúan sobre elementos en la estructura del objeto. Le permite definir nuevas operaciones sobre elementos sin cambiar sus clases.

Aplicabilidad Una estructura de objeto contiene muchos objetos de clase con diferentes interfaces y desea realizar algunas operaciones en estos objetos que dependen de sus clases específicas. Necesita realizar muchas operaciones diferentes y no relacionadas en los objetos de una estructura de objetos y desea evitar que estas operaciones "contaminen" las clases de estos objetos. Visitor le permite centralizar operaciones relacionadas y definirlas en una clase. Cuando muchas aplicaciones comparten una estructura de objeto, utilice el patrón de visitante para que cada aplicación contenga solo las operaciones que necesita utilizar. La clase que define la estructura del objeto rara vez cambia, pero a menudo es necesario definir nuevas operaciones sobre esta estructura. Cambiar la clase de estructura del objeto requiere redefinir la interfaz para todos los visitantes, lo que puede resultar costoso. Si las clases de estructura de objetos cambian con frecuencia, puede ser mejor definir estas operaciones en esas clases.