Hoy continuaremos con la sesión anterior
donde expliqué que los pequeños métodos eran buenos.
Hoy mostraré algunos ejemplos.
Pero primero, repasemos rápidamente nuestra sesión anterior
Enviar un mensaje lleva a una elección.
Una opción enmascarada porque varios posibles implementaciones
se llamará
Y Pharo hace una elección dependiendo del receptor del mensaje.
La jerarquía de clases define las opciones: Más clases = más opciones.
Y puedes agregar fácilmente nuevas elecciones mediante la creación de subclases.
Las subclases pueden redefinir o refinar el código de su superclase
Y enviando un mensaje
significa dar subclases La posibilidad de cambiar el comportamiento.
Hoy miraremos el método de plantilla de patrón de diseño.
Lo encontrarás en el manual de diseño de patrones.
¿Qué es un método de plantilla?
Es un esqueleto que define el comportamiento general
de un algoritmo, por ejemplo, con ganchos en el interior.
Y estos ganchos pueden ser redefinido por subclases.
Este es un algoritmo.
Hace algo, no sabemos exactamente qué.
Luego, hace algo en gancho Método 1,
luego algo más,
y luego algo en ganchoMetodo2.
Desde hookMethods 1 y 2 son ambos métodos completos,
pueden ser redefinidos en las subclases.
Hay 2 posibilidades, uno para el hookMethod 1 y 2.
Estos métodos pueden o no
tienen un comportamiento predeterminado.
Aquí, digamos que hookMethod 1 tiene un comportamiento predeterminado.
Esto significa que si la subclase no propone nada,
hookMethod 1 tiene un comportamiento predeterminado eso funciona
Del mismo modo, podríamos decir
ese hookMethod 2 no tiene un comportamiento predeterminado.
La subclase debe imperativamente definir uno.
Como diseñador de la clase, tu puedes elegir
si o no para determinar un comportamiento predeterminado.
Usaremos printString Como primer ejemplo.
La idea es que si envío un mensaje printString a un objeto,
Obtengo una cadena de caracteres que representa este objeto
Aquí tengo un retraso.
He creado una demora de 10 segundos.
Si envío un mensaje printString a esta demora,
Tengo un retraso y entre paréntesis, un milisegundo de valor para la demora.
El método printString se implementa en la clase de objeto como esta.
Envía el mensaje printStringLimitedTo
Esta implementación
recupera una cadena de caracteres eso representa
el objeto.
Y si esta cadena de caracteres es demasiado largo,
podemos cortarlo en un cierto límite.
Luego al final, Concatenamos con '... etc ...'
decir que la cadena no está hecha.
Lo importante aquí
es que printStringLimitedTo envía un mensaje printOn a ti mismo.
Este es el metodo
que lo hará o no ser redefinido en las subclases.
Si miro lo que devuelve printString
para un nodo y para una manzana,
El nodo nuevo devuelve un nodo.
Este es el printString de la clase Nodo.
Y aquí en Apple, tenemos el printString de la clase Apple.
Vemos que este comportamiento y el comportamiento predeterminado
se implementan en el objeto de clase.
Entonces, el comportamiento predeterminado de printString para cualquier objeto que sea
es uno:
Recupera los nombres de clase.
En este caso, Node y Apple.
Y dos, si el nombre de la clase comienza con una vocal,
utilizamos el prefijo "an".
Si comienza con una consonante, utilizamos el prefijo "a".
Así es como nosotras "un nodo" y "una manzana".
Este es el comportamiento predeterminado.
Pero es posible cambiar este comportamiento predeterminado
refinando printOn.
Por un retraso,
nosotros vemos eso el printString de una demora
comienza con la devolución predeterminada de printOn.
Eso es "un retraso".
Pero luego, podemos agregar la demora en milisegundos entre paréntesis.
Esto es exactamente lo que el método printOn.
Comienza preguntando a la superclase para el printString predeterminado.
Después, abre un paréntesis
con un número predeterminado de milisegundos,
y luego cierra los paréntesis.
Solo miramos el refinamiento.
La clase de retraso refina la implementación
del método printOn en la clase de objeto.
Pero una clase también puede redefinir completamente el comportamiento
Este es el caso de los booleanos, por ejemplo.
Si muestro falso,
devolverá falso
No tenemos "un falso"
simplemente "falso".
Para esto, solo enviamos la cadena de caracteres "falsa"
en el flujo de variables printOn.
Eso es una redefinición completa.
Otro ejemplo de redefinición completa es intervalos.
Un intervalo define un conjunto de valores
situado entre un valor mínimo y máximo.
El intervalo de 1 a 100 se muestra mediante: (1 a:100)
El intervalo de 1 a:100 por:3
1, 4 y así sucesivamente,
se muestra de la misma manera con el "by" adicional.
¿Cómo se implementa esto?
La clase de intervalo redefine el método printOn
y envía mensajes diferentes para transmitir variables.
Empezamos abriendo paréntesis.
Los paréntesis aquí y aquí.
Luego mostramos el valor inicial o el primer número del intervalo,
que es este "1" aquí, y este "1" aquí.
Luego escribimos 'a:'.
Y escribimos el valor final:"100",
y "100".
Si hay un "by" eso es diferente del predeterminado "1",
escribimos el "a".
Y al final, cerramos los paréntesis.
Vimos que printString
usa el patrón de diseño método de plantillas para que las clases
puede implementar su propia representación textual.
Ahora veremos otro ejemplo, que es copia de objeto.
¿Qué hace la copia?
Te permite tomar un objeto y crea un código desde él.
Copiar objetos es complejo.
Puede haber diferentes estrategias.
Cada clase puede decidir
cual es la copia de sus instancias debería parecerse.
Hay una simple solución de método de plantilla
que usa copy y postCopy.
Copiar es un método de plantilla y postCopy es un gancho.
En la clase de objeto hay un método de copia.
Te dejaré leer el comentario.
En este metodo, enviamos shallowCopy
como un mensaje para ti mismo,
seguido de postCopy en el resultado
¿Qué hace shallowCopy?
Crea un nuevo objeto que comparte todas las variables de instancia
con el objeto base.
Tenemos dos objetos y sus variables de instancia son las mismas.
Si modifico la variable de instancia de un objeto, modifico el otro también.
Ese es el comportamiento predeterminado
de poca profundidad.
Según lo que hace postCopy,
las variables serán compartidas o no.
Si postCopy está vacío, todas las variables se comparten
Pero las clases pueden decidir poner cosas diferentes en postCopy
para compartir ciertas variables o nada en absoluto.
La configuración predeterminada de postCopy comparte todo
Simplemente devuelve el objeto actual.
Pero también podríamos imaginar otras aplicaciones para postCopy.
Por ejemplo, en la clase Bag.
Bag es un tipo de colección
y su método postCopy copia su contenido
Por lo tanto, una bolsa es una variable de instancia de contenido,
y los diseñadores de la clase Bag decidió que
cuando copia una bolsa,
no quieres compartir la variable de contenido,
Quieres variables separadas.
Tienen el mismo valor inicial pero puedes modificar solo uno.
Aquí la idea es:
postCopy es un mensaje enviado para copiar, o el nuevo objeto,
que comparte todas las variables de instancia.
Si no queremos compartirlos,
creamos otros nuevos y decidir sobre su valor.
Aquí en mi variable de contenido,
Pondré una copia de los contenidos iniciales.
De esa manera no los comparto.
Cada copia de mi bolsa tiene sus propios contenidos.
Con el diccionario, vamos aún más lejos.
Un diccionario es una colección de pares clave-valor,
o una colección de asociaciones.
No solo queremos copiar la colección...
Si copiamos un diccionario, queremos copiar la colección,
y cada diccionario Tiene su propia colección de pares ...
Pero también queremos que cada par ser diferente.
Entonces, si modifico uno, no modificará el otro lado.
Para hacer esto, copio la tabla, pero también copia
cada par adentro.
Esto es lo que está sucediendo aquí.
Para concluir, el patrón de diseño El método de plantilla es muy común.
Es una señal de buen diseño.
Si haces un buen diseño de objetos, tendrás muchos métodos de plantilla.
Es perfectamente normal y algo bueno.
Entonces, no dudes en usarlos.
Esta técnica permite subclases definir comportamiento
y modificar parcialmente El comportamiento de la superclase.