Tipos de Patrones de Diseño - Definición y Código de Ejemplo
En este artículo, nos enfocaremos en profundizar sobre los tipos de patrones que existen en programación, y su aplicación en Java.
Algunas personas pueden pensar que son solo básicas herramientas para crear programas con más funcionalidad y calidad, pero al final no es el caso. Los patrones de diseño java, como todo en la vida, tienen un lado positivo si se utiliza de forma adecuada.
Estos tipos de patrones están clasificados principalmente en tres categorías: patrones creativos, estructurales y de comportamiento, los cuales serán profundizados en las siguientes páginas.
Esperamos que esta información te sea útil para programar de la manera correcta.
Patrones creacionales
Patrón de Diseño Singleton
Es uno de los patrones de diseño más populares en Java, es decir un tipo de patrones de diseño que provee una clase con solo una instancia y proporciona un acceso global a esa clase. Su principal objetivo es instanciar una sola vez la clase.
```java
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
```
Patrón de Diseño Factory
Es un tipo de tipos de patrones que provee un método de creación de objetos y ayuda en la separación del proceso de creación del objeto a partir de su representación. La principal ventaja es que si cambia el diseño del producto, no tienes que modificar los clientes del mismo.
```java
public abstract class Factory {
public abstract Producto crearProducto();
}
public class ConcreteFactory extends Factory{
@Override
public Producto crearProducto() {
return new Producto();
}
}
```
Patrón de Diseño Prototype
Es un tipo de patrones de diseño que provee una clase con una interfaz para clonar objetos sin tener que realizar un nuevo objeto.
```java
public class Prototype implements Cloneable {
private String propiedad1;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
```
Patrón de Diseño Builder
Es un tipo de tipos de patrones que provee una clase para facilitar el acceso a las propiedades y realizar la instanciación de manera más fácil.
```java
public class Director {
public void construye(ProductoBuilder productoBuilder) {
// Implementación
}
}
public abstract class Builder {
public abstract void construye();
public Producto obtener() {
return new Producto();
}
}
```
Patrón de Diseño Abstract Factory
Es un tipo de tipos de patrones que provee una interfaz para crear familias de objetos sin especificar los tipos de objetos.
```java
public abstract class AbstractFactory {
public abstract ComponenteA criarComponentea();
public abstract ComponenteB criarComponenteb();
}
public class ConcreteFactory extends AbstractFactory{
@Override
public ComponenteA criarComponentea() {
return new ComponenteA();
}
@Override
public ComponenteB criarComponenteb() {
return new ComponenteB();
}
}
```
Patrón Singleton
El patrón Singleton es un patrón creacional del cual su objetivo es crear una sola instancia de una clase y proveer un solo punto de acceso global para ese objeto.
Este patrón garantiza que la única existencia en todo el programa es una. Algunas veces se necesita esta funcionalidad, por ejemplo, al trabajar con bases de datos.
Entre sus formas más comunes de implementación están la Instanciación Ansiosa o Perezosa y la seguridad para subprocesos.
La sintaxis para un patrón Singleton puede ser la siguiente:
```java
public class Persona {
private static Persona persona;
private int edad;
public int getEdad() {
return this.edad;
}
public void setEdad(int edad) {
this.edad = edad;
}
}
``
setEdad()
Con los métodosy
getEdad()`, podemos manejar la información que queramos guardar o recuperar de nuestra clase.
El siguiente es un ejemplo completo, para que se comprenda mejor cómo implementarlo.
Fábrica abstracta (Abstract Factory)
El patrón de diseño Fábrica Abstracta, también conocido como el patrón de creación Fábrica, es una categoría dentro de los patrones de diseño Java que permite la creación de objetos que pertenecen a un conjunto de productos relacionados o dependientes.
Este tipo de patrón se utiliza cuando se necesita crear familias de objetos y, a menudo, también incluye la creación de sus dependencias. Por lo tanto, los tipos de patrones como el de Fábrica Abstracta son de gran utilidad en proyectos que involucran una interfaz gráfica de usuario o juegos donde existen elementos relacionados.
```java
// Clase fábrica concreta para creación de vehículos.
public class VehiculoFactory implements Factory {
@Override
public Auto crearAuto() {
return new Camioneta();
}
@Override
public Moto crearMoto() {
return new Motocicleta();
}
}
```
Constructor compartido (Shared Constructor)
El constructor compartido es un patrón de diseño estructural que permite compartir código entre clases relacionadas. Este patrón se utiliza para evitar la repetición de código y mejorar la reutilización de comportamientos.
Ventajas
- Mejora la reutilización de código: Al compartir el constructor entre varias clases, puedes reutilizar el código sin tener que copiarlo.
- Reduce la complejidad del proyecto: El constructor compartido ayuda a mantener una estructura más simple y ordenada en tu proyecto.
Implementación
Para implementar el constructor compartido, debes definir un método de inicialización común para las clases relacionadas. Este método debe ser llamado desde cada clase que utilice la inicialización compartida.
Ejemplo de Código
Supongamos que tenemos dos clases: Persona
y Empleado
, ambas necesitan realizar una inicialización común para su constructor.
```java
public class Persona {
protected String nombre;
public Persona(String nombre) {
this.nombre = nombre;
}
}
public class Empleado extends Persona {
private double salario;
public Empleado(String nombre, double salario) {
super(nombre); // Llamamos al constructor de la clase base (Persona)
this.salario = salario;
}
}
```
En este ejemplo, el método super(nombre)
llama al constructor compartido del padre (Persona
) y establece el valor de la propiedad nombre
en cada instancia de Empleado
.
Prototype
El patrón de creación Prototype es uno de los tipos más interesantes, ya que permite la copia y reproducción de objetos existentes para facilitar el proceso de desarrollo. A menudo se utiliza cuando queremos reproducir un objeto original y crear una nueva instancia.
Este patrón consiste en crear un objeto prototipo con todos los datos y atributos necesarios, y luego clonarlo cada vez que sea necesario. De esta manera, evitamos tener que reescribir el mismo código varias veces para inicializar un objeto con una estructura similar.
Para implementar este patrón en java tenemos dos maneras de proceder:
- Clonar manualmente: En esta opción creamos un constructor clon del prototipo, donde dentro se utiliza un algoritmo (que no es tan complicado) para obtener una nueva copia.
- Uso de clone() : La clase Object de Java tiene el método clone(), por lo que podemos utilizarlo en nuestras clases para clonar objetos y, si así se decide, puede ser mejor implementar el Cloneable interfacio.
Estructura del prototipo
El patrón estructural Prototype también es bastante interesante, ya que permite a las clases crear estructuras complejas de datos sin tener que preocuparse por la relación entre los componentes. Este tipo de patrones es más común en el desarrollo web donde se trabajan con frameworks como Spring o Hibernate.
En java podemos utilizar el prototipo para implementar una estructura que nos permita seguir un flujo de negocio de forma lineal, así tenemos objetos relacionados a otros por medio del prototipo.
Patrones estructurales
Están diseñados para la mejora y organización de estructuras dentro del programa.
Hay una serie de patrones de diseño java que son bastante populares debido a su amplia utilidad:
- Decoupling: Este patrón de diseño está enfocado en separar cada parte del sistema.
- Flyweight: Es un patrón creacional, cuya función es reducir la cantidad de memoria utilizada en la aplicación.
Flyweight
El Patrón Flyweight es un patrón estructural que permite reducir el uso de memoria en objetos muy similares, restando sus propiedades y compartiendo información entre ellos.
En tipos de patrones, los flyweights son una variación del patrón de diseño Singleton. Un objeto singleton generalmente tiene estado propio (por ejemplo, valores de instancia), pero un Flyweight no tiene estado. Su objetivo es almacenar o compartir datos entre varias instancias.
El nombre "Flyweight" proviene del idioma inglés; en su contexto original, un "flyweight" era una pesa muy ligera utilizada para pesas de halteres. De manera similar al flyweight, este patrón busca ahorrar memoria.
Mould de adjacencia (Adjacency List)
El Mould de Adjacencia es un tipo de estructura de datos que representa las relaciones entre elementos en un conjunto.
Patrones de diseño java
En el contexto de la programación, los patrones de diseño son soluciones a nivel de diseño para problemas recurrentes. Estos patrones proporcionan una forma estandarizada de resolver problemas comunes, permitiendo a los desarrolladores crear código más modular y reutilizable.
Tipos de patrones
Hay tres tipos principales de patrones:
- Creacionales: Estos patrones están diseñados para la instanciación de clases y objetos. Se utilizan cuando se necesita crear una nueva instancia de un objeto.
- Estructurales: Estos patrones son diseñados para mejorar la estructura y composición de las clases, agregando funcionalidad sin cambiar mucho su estructura.
Un ejemplo del Mould de Adjacencia sería representar a los países en un mapa mundial. En este caso, cada país es una instancia y se relaciona con otros países por fronteras.
Composite
El patrón Composite es un patrón estructural que permite a una clase tener una jerarquía de objetos y proporciona una forma sencilla para manipularlos como si fueran un solo objeto. Este patrón se utiliza comúnmente en situaciones donde se tiene que procesar o mostrar un conjunto de objetos similares, pero con diferentes características.
Tipos de patrones: Los patrones de diseño son soluciones a nivel de diseño para problemas recurrentes en programación, y pueden ser divididos en tres categorías: creacionales, estructurales y de comportamiento. El Composite es un ejemplo de patrón estructural.
En Java, el patrón Composite se utiliza a menudo cuando se tiene que trabajar con colecciones de objetos, como listas o árboles de nodos. Por ejemplo, si se tiene que dibujar una jerarquía de figuras geométricas, cada figura puede ser un objeto del tipo "Figura", y cada hijo de la jerarquía puede ser un objeto del mismo tipo que tenga ciertas propiedades o comportamientos adicionales.
El patrón Composite se caracteriza por la capacidad de tratar a los objetos individuales como si fueran una sola unidad, permitiendo realizar operaciones sobre todos los objetos de una manera uniforme y flexible.
Decorator
El patrón Decorator es uno de los tipos de patrones que se utilizan en la programación para agregar funcionalidades a objetos existentes sin afectar su comportamiento base.
Un ejemplo clásico del uso del patrón Decorator es el sistema de café. En este caso, tenemos diferentes tipos de cafes, como Espresso y Cappuccino, y también tenemos diferentes opciones adicionales como azúcar o crema. Podemos utilizar el patrón Decorator para agregar estas opciones adicionales a los cafes sin crear una clase nueva por cada combinación posible.
Un ejemplo en patrones de diseño java del uso del patrón Decorator es el siguiente:
```java
interface Coffee {
String getDesc();
}
class Espresso implements Coffee{
public String getDesc() {
return "Espresso";
}
}
abstract class DecoratorCoffee implements Coffee {
private final Coffee coffee;
protected DecoratorCoffee(Coffee coffee) {
this.coffee = coffee;
}
@Override
public String getDesc() {
return coffee.getDesc();
}
}
class Mocha extends DecoratorCoffee{
public Mocha(Coffee coffee) {
super(coffee);
}
@Override
public String getDesc() {
return "Mocha "+super.getDesc();
}
}
```
En este ejemplo, el patrón Decorator nos permite agregar funcionalidades a los cafes existentes sin afectar su comportamiento base. El decorador Mocha es capaz de dar una descripción más detallada del café que le estamos pasando como argumento.
Patrones de comportamiento
Los patrones de comportamiento son aquellas estrategias que se utilizan para facilitar la comunicación entre objetos y clases en programación. A continuación, te presento algunos tipos importantes:
1. El patron de Obervador
El patrón de diseño Observador es un patrón creacional que permite que un objeto (el observador) monitoree el cambio en otro objeto (el observable). La comunicación entre ambos objetos se logra mediante eventos. En este patrón, la clase observable puede notificar a sus observadores sobre cualquier tipo de evento.
Código de ejemplo:
```java
public interface Observer {
void actualizar(String mensaje);
}
public class Notificador implements Observable{
@Override
public void notificarObservers() {
for (Observer observer: observers){
observer.actualizar("El patrón ha sido modificado");
}
}
public void agregarObservador(Observer observador) {
observers.add(observador);
}
private List<Observer> observers = new ArrayList<>();
}
public class MiClase implements Observer{
@Override
public void actualizar(String mensaje){
System.out.println("Actualizado: "+mensaje);
}
}
```
2. El patron de Estado
El patrón de estado permite a un objeto cambiar su comportamiento en función del contexto, o estado. Es muy útil cuando se tiene más de una acción que puede ser realizada por el mismo objeto pero con diferentes resultados dependiendo de su estado.
Código de ejemplo:
```java
public interface Estado {
void hacerAccion(String accion);
}
public class Conductor implements Estado {
@Override
public void hacerAccion(String accion) {
System.out.println(accion+" del conductor");
}
}
public class Pasajero implements Estado {
@Override
public void hacerAccion(String accion) {
System.out.println(accion+" del pasajero");
}
}
```
Modelo de vista modelo (Model View Model, MVVM)
El Modelo de vista modelo es un patrón de diseño structurales utilizado para separar la presentación y lógica de una aplicación en tres componentes independientes: el Modelo, la Vista, y el Controlador.
Este patrón se utiliza principalmente en interfaces gráficas de usuario, pero también puede ser aplicado a otros contextos que requieren separación clara entre la información del negocio, la presentación y la lógica que maneja esa información.
En Java, este patrón se implementa mediante la creación de un objeto que representa el Modelo (el controlador), otro que representa la Vista y finalmente otro que representa a la aplicación que usa ambas.
Observable
El patrón de comportamiento, también conocido como el patrón Observer, es un patrón de patrones de diseño Java que permite a objetos comunicarse entre sí sin mantener una relación explícita. Este patrón se utiliza cuando hay una dependencia entre objetos y necesitas ser notificado cuando su estado cambie.
En este patrón, hay dos tipos de clases involucradas: Observador y Observable. La clase observable es la que va a notificar a sus observadores cada vez que su estado cambie. El objeto observador, por otro lado, es el encargado de recibir la notificación.
Tipos de patrones como estos nos ayudan a separar la responsabilidad entre los diferentes objetos en un sistema, haciendo que sea más fácil entender y mantener su estructura.
En cuanto al código de ejemplo, podemos implementarlo como sigue:
```java
public interface Observador {
public void update(String mensaje);
}
public class ClaseObservada implements Observador {
private List
public void agregarObservador(Observador o) {
this.observadores.add(o);
}
public void eliminarObservador(Observador o) {
this.observadores.remove(o);
}
public void notificarObservadores(String mensaje) {
for (Observador observador : this.observadores) {
observador.update(mensaje);
}
}
}
public class Principal {
public static void main(String[] args) {
ClaseObservada co = new ClaseObservada();
Observador o1 = new ObservadorClase1();
Observador o2 = new ObservadorClase2();
co.agregarObservador(o1);
co.agregarObservador(o2);
co.notificarObservadores("Hola, estoy vivo!");
}
}
public class ObservadorClase1 implements Observador {
@Override
public void update(String mensaje) {
System.out.println("Recibido: " + mensaje);
}
}
public class ObservadorClase2 implements Observador {
@Override
public void update(String mensaje) {
System.out.println("Notificado: " + mensaje);
}
}
```
En este ejemplo, tenemos la clase tipos de patrones ClaseObservada que implementa la interfaz Observador. Esta clase tiene un listado de observadores y métodos para agregar y eliminar observadores del listado.
La clase Principal crea una instancia de ClaseObservada y agrega dos observadores a su lista, luego notifica a todos los observadores en el listado cada vez que ejecuta la método notificarObservadores con algún mensaje.
Estado de objeto (State of Object)
El patrón de diseño Estado del Objeto es un tipo de patrones de diseño Java que define el comportamiento de una clase a partir de sus subclases, esto se logra haciendo uso de interfaces y herencia en los mismos. Esta interfaz está implementada por cada clase hija, de la siguiente manera: esta clase hija extiende (hereda) directamente del padre pero debe cumplir con las declaraciones de los métodos de la interfase hija.
Interprete de comando (Command Interpreter)
El patrón de diseño Interprete de comando es un tipo de patrones de diseño en Java utilizado para encapsular una solicitud como objeto, que puede entonces ser pasada a otros objetos. Esto permite solicitudes complejas o procesos difíciles de manejar de manera más organizada.
En lugar de llamar a los métodos directamente del receptor, el patrón de comando crea un objeto comando que se encarga de recibir la solicitud y ejecutar las acciones necesarias para satisfacerla. Esta encapsulación puede ayudar a mejorar la flexibilidad, reutilizabilidad y escalabilidad de la aplicación.
Un ejemplo básico es un sistema que permite realizar pedidos en una tienda en línea:
- Cuando un cliente selecciona productos para comprar, el patrón de comando crea un objeto pedido con la información del producto.
- El objeto comando se encarga de procesar el pago y enviar la orden al proveedor.
Este patrón es especialmente útil cuando hay varias acciones que pueden realizar una tarea específica. Al utilizar un objeto comando, puedes fácilmente cambiar o reemplazar las acciones sin afectar los demás partes del sistema.
```
public interface Comando {
void ejecutar();
}
public class ComandoAgregarItem implements Comando {
@Override
public void ejecutar() {
System.out.println("Se agregó un nuevo item al pedido.");
}
}
public class ComandoRestaurarStock implements Comando {
@Override
public void ejecutar() {
System.out.println("El stock se ha restaurado a los niveles anteriores.");
}
}
```
El patrón de comando es un patrones de diseño en Java muy útil para encapsular solicitudes complejas y realizar acciones específicas en diferentes partes del sistema.
```java
public class SistemaDeTienda {
public void procesarOrden(Comando comando) {
comando.ejecutar();
}
public static void main(String[] args) {
Comando agregarItem = new ComandoAgregarItem();
Comando restaurarStock = new ComandoRestaurarStock();
System.out.println("Ejemplo del patrón de comando:");
SistemaDeTienda sistemaDeTienda = new SistemaDeTienda();
sistemaDeTienda.procesarOrden(agregarItem);
sistemaDeTienda.procesarOrden(restaurarStock);
}
}
```
La salida de la aplicación será:
Ejemplo del patrón de comando:
Se agregó un nuevo item al pedido.
El stock se ha restaurado a los niveles anteriores.
Conclusión
Es importante mencionar que los tipos de patrones son una herramienta fundamental para resolver problemas recurrentes en programación y mejorar la estructura y composición de nuestras clases.
Los patrones de diseño java, como se les denomina comúnmente, permiten crear soluciones más claras y escalables a nuestros problemas de diseño.
Al entender y aplicar adecuadamente estos patrones, podemos mejorar significativamente nuestra capacidad para crear software robusto y mantenible.
Si quieres conocer otros artículos parecidos a Tipos de Patrones de Diseño - Definición y Código de Ejemplo puedes visitar la categoría Programacion.
Deja una respuesta
Contenido que te pude interesar