| Clasificación | Intención | Otros nombres | Motivación | Aplicabilidad | Estructura | Participantes |
| Colaboraciones | Consecuencias | Implementación | Patrones Relacionados |
| Idioms en C++ |
| Eliminar copias físicas innecesarias de objetos. |
| Reference Counting |
| Retomando el ejemplo de la clase String en la forma
canónica de una clase, se implementaba una copia física
en el constructor por copia y en la operación de asignación
entre Strings. Esta implementación hace que cada vez que se pase
un String como argumento de una función o en operaciones de asignación
se realice una nueva copia de la representación, en algunos casos
innecesaria, por la misma manipulación de los objetos.
Se busca compartir la representación de las cadenas siempre que sea posible, eliminando el concepto de copia física por el de copia lógica, donde varios objetos comparten la misma representación mientras permanezcan sin cambio. |
| Use este idiom para clases que son frecuentemente copiadas por asignación o paso de parámetros, partiuclarmente si los objetos son grandes o complejos y la copia es costosa en tiempo y espacio de memoria. Uselo cuando varias copias lógicas del objeto puedan existir, donde los datos no requieran ser copiados; por ejemplo, un objeto que represente una ventana que es pasado entre funciones o información compartida por varios manejadores, donde cada uno de ellos quiera una copia para acceder al recurso. |
Se retoma la estructura del idiom Manija
- Cuerpo para representar la copia compartida (Cuerpo) y los distintos
administradores (Manijas). Por ejemplo, la estructura de objetos para las
siguientes líneas de código
sería ![]() |
|
| El objeto cuerpo guarda el conteo de referencias y provee operaciones para manipularlo: agregar una nueva referencia, borrar una y desaparecer cuando ya no existan referencias al objeto. |
|
Se presentan tres formas de implementar este Idiom:
1. Forma general, derivada del Idiom Manija CuerpoEn esta forma la clase Cuerpo es la anterior Clase String (ahora denominada StringRep) que se encarga de la manipulación de la cadena; mientras que la clase Manija se encarga de la administración de la memoria. La implementación correspondiente es como sigue
En esta representación se deja todo el conocimiento de la forma
de manipulación de cadenas en la clase interna (StringRep) y el
manejo de referencias y manejo de memoria en la externa (String). Sin embargo,
tiene aún problemas de eficiencia, en particular en la operación
de suma de cadenas.
2. Una implementación más eficienteEn este caso se soluciona el problema de eficiencia del caso anterior. En esta opción se dejan las operaciones en la clase Manija (String) y se limita la clase Cuerpo (StringRep) a las operaciones de creación y destrucción. El código es como sigue
En esta implementación se alijera el proceso de creación de Strings en la operación suma. Se reutiliza la memoria creada en esta operación como base de la implementación del nuevo String. Una desventaja es la falta de separación entre las funciones de cada una de las clases. 3. Contador de ApuntadoresEn esta representación se usa la sobrecarga del operador ->. Por medio de esta sobrecarga se permite a un usuario de la clase Manija acceder a los servicios públicos de la clase Cuerpo
En este caso la clase String sigue administrando la memoria y la clase StringRep las operaciones de una cadena, sin embargo, estas ya no se reflejan en String sino que se acceden mediante el operador ->. Se separan claramente las funciones, pero es necesario utilizar la simbología de un apuntador sobre el objeto String para acceder a sus servicios. Esta implementación es útil para no tener que duplicar
cambios en la clase Manija causados en la clase Cuerpo.
|
| Manija - Cuerpo |