Está en la página 1de 3

PATRONES DE DISEÑO

1. SINGLETON (patrón creacional) Creamos un solo objeto en todo el programa, para que lo podríamos usar
para objetos de configuración, usuario, …
fun main(argumento: Array<String>) {
print("Ingrese el usuario: ")
usuario.usr = readln() // no hace falta crear variable porque llamamos al
objeto
print("Ingrese la contraseña: ")
usuario.pwd = readln()

println("el usuario es ${usuario.usr} y la contraseña es ${usuario.pwd}")


}

// singleton
/* no creamos una clase (plantilla de un objeto porque solo exitira uno en todo
el programa */
object usuario {
var usr:String =""
var pwd:String =""
}

2. OBSERVER (patrón de comportamiento) Creamos un objeto que cada vez que haya una modificación,
mande un aviso , por ejemplo un nuevo articulo avisar a todos los usuarios.
Por ejemplo, imaginemos que tenemos una aplicación de mensajería que notifica a los usuarios cuando reciben un
nuevo mensaje.
En este caso, el sujeto sería el mensaje y los observadores serían los usuarios que están suscritos a ese mensaje.
Cuando se recibe un nuevo mensaje, el sujeto notifica a todos sus observadores y éstos pueden actualizar su interfaz
de usuario para mostrar el nuevo mensaje.
// observer
/* Este patrón permite que un objeto, conocido como “sujeto”, notifique a sus
“observadores” cuando sucede un cambio en su estado.*/

fun main() {
val mensaje = Mensaje("Hola mundo")
val usuario1 = Usuario("Juan")
val usuario2 = Usuario("Ana")

mensaje.anadirObserver(usuario1)
mensaje.anadirObserver(usuario2)

mensaje.setContent("¿Cómo estás?")
}
/* Por ejemplo, podríamos tener una interfaz llamada Observable que define los métodos
agregar y eliminar observadores,
así como para notificar a los observadores (usuarios) cuando se produce un cambio en el
estado del sujeto (el mensaje). */
interface Observable<T> {
fun anadirObserver(observer: Observer<T>)
fun eliminarObserver(observer: Observer<T>)
fun notificarObservers()
}
/*También tendríamos una interfaz llamada Observer que define un método para actualizar
el estado del observador (usuario) cuando se produce un cambio en el sujeto(mensaje).*/
interface Observer<T> {
fun actualizar(data: T)
}
/* implementamos nuestro sujeto, clase Mensaje que implementa la interfaz Observable y
mantiene una lista de observadores.*/
class Mensaje(var cadena: String) : Observable<Mensaje> {
private val observers = mutableListOf<Observer<Mensaje>>()
fun setContent(content: String) {
content.also { this.cadena = it }
notificarObservers()
}

override fun anadirObserver(observer: Observer<Mensaje>) {


println("añadimos al observador")
observers.add(observer)
}

override fun eliminarObserver(observer: Observer<Mensaje>) {


println("Eliminamos Observadr")
observers.remove(observer)
}

override fun notificarObservers() {


observers.forEach { it.actualizar(this) }
}
}
/*Por último, implementamos nuestros observadores, una clase Usuario que implementa la
interfaz Observer y muestra el nuevo mensaje cuando se produce un cambio en el
sujeto.*/
class Usuario(var name: String) : Observer<Mensaje> {
override fun actualizar(data: Mensaje) {
println("Nuevo mensaje para $name: ${data.cadena}")
}
}

3. DECORATOR (patrón estructural)  permite agregar funcionalidades adicionales a un objeto de forma


dinámica, sin necesidad de crear subclases para cada combinación de funcionalidades.
Por ejemplo, imagina que queremos crear una aplicación que permita a los usuarios comprar pizzas con
diferentes ingredientes. Para ello, podemos crear una interfaz Pizza que define la funcionalidad básica de
una pizza, como su tamaño y su precio, y una clase base PizzaBase que implementa esta interfaz y que
representa una pizza básica sin ingredientes adicionales.

// Decorator
/* se implementa mediante la creación de una interfaz que define la funcionalidad base
del objeto a decorar,
* y una clase base que implementa esta interfaz y que servirá como punto de partida
para crear las decoraciones.
* Las decoraciones son clases que implementan la misma interfaz que el objeto base,
* y que contienen una referencia a un objeto de la clase base..*/

// Por ejemplo, queremos crear una aplicación que permita a los usuarios reservar
Habitaciones con diferentes caracteristicas.
fun main() {
val hab = JacuzziHabitacionDecorator(HabitacionBase(camas = 2), jacuzzi = true)
println("el precio de la habitacion es " + hab.precio) // imprime 24.0
val hab1 =
TerrazaHabitacionDecorator(JacuzziHabitacionDecorator(HabitacionBase(camas = 3),
jacuzzi = false))
println("El precio de la habitacion con terraza es " + hab1.precio) // imprime 34.0
}
/*
* Para ello, podemos crear una interfaz Habitacion que define la funcionalidad básica
de una habitacion, como camas y su precio, y
* una clase base HabitacionBase que implementa esta interfaz y que representa una
habitacion básica sin caracteristicas adicionales.
* */
interface Habitacion {
val camas: Int
val precio: Double
}

class HabitacionBase(override val camas: Int) : Habitacion {


override val precio: Double
get() = 10.0 * camas
}

/*
* podemos crear las diferentes decoraciones para agregar carateristicas a la
habitacion.
* Por ejemplo, una clase JacuzziHabitacionDecorator que agrega Jacuzzi o Ducha Masaje a
la habitacion dependiendo del valor jacuzzi
* a la Habitacion y aumenta su precio en 2€ o 4€ dependiendo de la opcion.
*/
class JacuzziHabitacionDecorator(private val habitacion: Habitacion,private val
jacuzzi: Boolean) : Habitacion {
override val camas: Int get() = habitacion.camas
override val precio: Double
get() {
return if (jacuzzi==true)
habitacion.precio + 4
else
habitacion.precio + 2
}

}
/*
* podemos crear otra para incluir si la habitación tiene terraza
* */
class TerrazaHabitacionDecorator(private val habitacion: Habitacion) : Habitacion {
override val camas: Int get() = habitacion.camas
override val precio: Double get() = habitacion.precio + 2

También podría gustarte