Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprende Desafío: Implementación de un Servicio TaskManager | Estructuras de Datos Avanzadas en Java
Quizzes & Challenges
Quizzes
Challenges
/
Estructuras de Datos en Java

bookDesafío: Implementación de un Servicio TaskManager

Práctica

Es momento de practicar. Tienes la tarea de escribir un servicio TaskManager que llevará el registro de tus tareas.

Con este servicio, el usuario puede agregar tareas, asignárselas y luego completarlas en un orden secuencial.

Vamos a comenzar a trabajar en esta tarea juntos, y luego continuarás por tu cuenta.

Pero primero, necesitas crear el modelo de tarea. Vamos a crear una clase Task:

Main.java

Main.java

copy
12345
public class Task { private int id; private String name; private String description; }

La clase Task contiene tres atributos: id, name y description. Cada tarea debe tener un nombre y una descripción, y id es un atributo necesario para cualquier estructura de datos.

¿De qué otra manera se accedería a los elementos? Los atributos también están protegidos por el modificador de acceso private porque no se desea que otras clases tengan acceso directo a los campos de esta clase, excepto a través del constructor o los getters.

Ahora, se implementarán estos getters y el constructor. Esto se puede realizar fácilmente utilizando la combinación de Control + Return en un MacBook o Alt + Ins en Windows.

Después de las operaciones realizadas, se tiene la siguiente clase Task:

Task.java

Task.java

copy
12345678910111213141516171819202122232425262728293031323334
package codefinity.taskManager; public class Task { private int id; private String name; private String description; public Task(int id, String name, String description) { this.id = id; this.name = name; this.description = description; } public int getId() { return id; } public String getName() { return name; } public String getDescription() { return description; } @Override public String toString() { return "Task{" + "id=" + id + ", name='" + name + '\'' + ", description='" + description + '\'' + '}'; } }

Servicios

Se utilizará un servicio de tablero de tareas muy simplificado, por lo que se implementará un servicio que permita agregar tareas, marcarlas como completadas y verificar si existen tareas en la cola.

Esta clase se denominará TaskQueueService. Para comenzar, es necesario definir una interfaz con estas tareas:

TaskQueueService.java

TaskQueueService.java

copy
123456789
package codefinity.taskManager; public interface TaskQueueService { void addTask(Task task); Task getNextTask(); boolean isEmpty(); }

Esta interfaz define 3 métodos que las clases de implementación deben implementar. Estos métodos incluyen agregar una tarea, pasar a la siguiente tarea (lo que implica que el usuario ya ha completado la tarea anterior) y un método para verificar si existen tareas en la cola.

Perfecto, ahora se creará una clase de implementación que sobrescribirá e implementará todos estos métodos:

TaskQueueServiceImpl.java

TaskQueueServiceImpl.java

copy
12345678910
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl { private Queue<Task> taskQueue = new LinkedList<>(); }

Creamos un atributo privado que se utilizará únicamente dentro de esta clase de servicio.

Vale la pena hacer una pequeña digresión para hablar sobre las clases de servicio, que desempeñan un papel clave en la POO.

¿Qué son las clases de servicio?

Las clases de servicio están diseñadas para realizar operaciones específicas. Heredan de interfaces de servicio e implementan sus métodos. Este enfoque mejora la mantenibilidad y escalabilidad del código, siguiendo los principios SOLID, que explorarás en un curso aparte.

Por ahora, es fundamental comprender que las clases de servicio existen únicamente para realizar operaciones sobre otros objetos.

Por ejemplo, Si escribes una calculadora, tendrás una clase separada que almacenará el valor del número sobre el que operas. Las operaciones reales se realizarán utilizando una clase de servicio donde se definen la suma, resta, etc.

Espero que esto aclare el propósito de las clases de servicio en la resolución de la tarea actual.

Implementación del servicio

Nuestro siguiente paso es mostrar explícitamente que esta clase implementa la interfaz TaskQueueService.

Para lograr esto, utilizamos la palabra clave implements seguida del nombre de la interfaz. Esto asegura que nuestra clase herede el comportamiento definido por la interfaz.

Dado que las interfaces solo proporcionan declaraciones de métodos, se deben sobrescribir e implementar estos métodos en nuestra clase.

Ahora, en nuestra clase, se muestran todos los métodos que deben ser sobrescritos. ¡Procedamos a hacerlo!

TaskQueueServiceImpl.java

TaskQueueServiceImpl.java

copy
1234567891011121314151617181920212223242526
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import codefinity.taskManager.TaskQueueService; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl implements TaskQueueService { private Queue<Task> taskQueue = new LinkedList<>(); @Override public void addTask(Task task) { taskQueue.offer(task); } @Override public Task getNextTask() { return taskQueue.poll(); } @Override public boolean isEmpty() { return taskQueue.isEmpty(); } }

En nuestro caso, no se realizó nada demasiado complicado. Simplemente utilizamos los métodos de la clase Queue para implementar correctamente nuestros métodos. Así, una estructura de datos como una cola facilita la vida a todos los programadores de Java.

Utilizamos el método offer() para agregar, el método poll() para eliminar y el método isEmpty() para comprobar si la cola está vacía.

Ahora es tu turno de participar en la resolución de este problema. Deberás implementar una clase de servicio, cuya interfaz crearemos juntos:

Main.java

Main.java

copy
12345
package codefinity.taskManager; public interface TaskProcessorService { void processTasks(); }

Hemos creado una interfaz de servicio con un método: processTasks(), que, al ser invocado, debe comenzar a ejecutar todas las tareas hasta que la lista de tareas esté vacía. Este método representa a un usuario comenzando a realizar tareas.

Tarea

La tarea consiste en escribir una clase TaskProcessorServiceImpl que debe implementar la interfaz TaskProcessorService. Esta clase debe tener un método para procesar todas las tareas, lo que significa que debe utilizar métodos del servicio TaskQueueService. Se puede utilizar composición creando una instancia de esta clase dentro de la clase que se necesita implementar, por ejemplo:

Main.java

Main.java

copy
1234567
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.TaskQueueService; public class TaskProcessorServiceImpl { TaskQueueService taskQueueService = new TaskQueueServiceImpl(); }

En general, ya hay una composición preparada en la parte superior para tu tarea. A continuación, solo necesitas implementar un método utilizando una instancia de esta clase.

Después de eso, debes crear un constructor que inicialice este objeto de la clase taskQueueService.

De esta manera, podrás utilizar los métodos de este objeto. También es evidente que, para el procesamiento de tareas, necesitas pasar la cola con la que trabajará el taskProcessor.

El resto de la tarea queda a tu cargo. Se proporcionarán pistas en el archivo README.md. Una vez que tu solución esté lista, haz clic en el botón "Run Tests", y las pruebas unitarias que he escrito comprobarán tu solución.

  1. Primero, debes utilizar composición y crear una instancia de la clase TaskQueue. Luego, también añade su inicialización en el constructor.
  2. A continuación, implementa la interfaz TaskProcessorImpl y sobrescribe sus métodos.
  3. En la implementación de la interfaz, utiliza un bucle while con el método isEmpty() como condición.
  4. Dentro del bucle while, utiliza el método taskQueueService.getNextTask(), indicando que la tarea está completada. Muestra información en pantalla usando System.out.println() - "Processing Task: " + task.
  5. Cuando el bucle termine su trabajo, muestra en pantalla "All tasks processed.".
  6. Ejecuta las pruebas y verifica la corrección de tu solución.
package codefinity.taskManager.taskManagerImpl;

import codefinity.taskManager.Task;
import codefinity.taskManager.TaskProcessorService;
import codefinity.taskManager.TaskQueueService;

public class TaskProcessorServiceImpl implements TaskProcessorService {
    private final TaskQueueService taskQueueImpl;

    public TaskProcessorServiceImpl(TaskQueueService taskQueueImpl) {
        this.taskQueueImpl = taskQueueImpl;
    }

    @Override
    public void processTasks() {
        while (!taskQueueImpl.isEmpty()) {
            Task task = taskQueueImpl.getNextTask();
            System.out.println("Processing Task: " + task + ";");
        }
        System.out.println("All tasks processed successfully.");
    }
}
¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 2. Capítulo 3

Pregunte a AI

expand

Pregunte a AI

ChatGPT

Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla

Suggested prompts:

Can you explain how the TaskQueueService works in this context?

What should the output look like when processing tasks?

Is there a specific format for the Task class's toString() method?

bookDesafío: Implementación de un Servicio TaskManager

Desliza para mostrar el menú

Práctica

Es momento de practicar. Tienes la tarea de escribir un servicio TaskManager que llevará el registro de tus tareas.

Con este servicio, el usuario puede agregar tareas, asignárselas y luego completarlas en un orden secuencial.

Vamos a comenzar a trabajar en esta tarea juntos, y luego continuarás por tu cuenta.

Pero primero, necesitas crear el modelo de tarea. Vamos a crear una clase Task:

Main.java

Main.java

copy
12345
public class Task { private int id; private String name; private String description; }

La clase Task contiene tres atributos: id, name y description. Cada tarea debe tener un nombre y una descripción, y id es un atributo necesario para cualquier estructura de datos.

¿De qué otra manera se accedería a los elementos? Los atributos también están protegidos por el modificador de acceso private porque no se desea que otras clases tengan acceso directo a los campos de esta clase, excepto a través del constructor o los getters.

Ahora, se implementarán estos getters y el constructor. Esto se puede realizar fácilmente utilizando la combinación de Control + Return en un MacBook o Alt + Ins en Windows.

Después de las operaciones realizadas, se tiene la siguiente clase Task:

Task.java

Task.java

copy
12345678910111213141516171819202122232425262728293031323334
package codefinity.taskManager; public class Task { private int id; private String name; private String description; public Task(int id, String name, String description) { this.id = id; this.name = name; this.description = description; } public int getId() { return id; } public String getName() { return name; } public String getDescription() { return description; } @Override public String toString() { return "Task{" + "id=" + id + ", name='" + name + '\'' + ", description='" + description + '\'' + '}'; } }

Servicios

Se utilizará un servicio de tablero de tareas muy simplificado, por lo que se implementará un servicio que permita agregar tareas, marcarlas como completadas y verificar si existen tareas en la cola.

Esta clase se denominará TaskQueueService. Para comenzar, es necesario definir una interfaz con estas tareas:

TaskQueueService.java

TaskQueueService.java

copy
123456789
package codefinity.taskManager; public interface TaskQueueService { void addTask(Task task); Task getNextTask(); boolean isEmpty(); }

Esta interfaz define 3 métodos que las clases de implementación deben implementar. Estos métodos incluyen agregar una tarea, pasar a la siguiente tarea (lo que implica que el usuario ya ha completado la tarea anterior) y un método para verificar si existen tareas en la cola.

Perfecto, ahora se creará una clase de implementación que sobrescribirá e implementará todos estos métodos:

TaskQueueServiceImpl.java

TaskQueueServiceImpl.java

copy
12345678910
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl { private Queue<Task> taskQueue = new LinkedList<>(); }

Creamos un atributo privado que se utilizará únicamente dentro de esta clase de servicio.

Vale la pena hacer una pequeña digresión para hablar sobre las clases de servicio, que desempeñan un papel clave en la POO.

¿Qué son las clases de servicio?

Las clases de servicio están diseñadas para realizar operaciones específicas. Heredan de interfaces de servicio e implementan sus métodos. Este enfoque mejora la mantenibilidad y escalabilidad del código, siguiendo los principios SOLID, que explorarás en un curso aparte.

Por ahora, es fundamental comprender que las clases de servicio existen únicamente para realizar operaciones sobre otros objetos.

Por ejemplo, Si escribes una calculadora, tendrás una clase separada que almacenará el valor del número sobre el que operas. Las operaciones reales se realizarán utilizando una clase de servicio donde se definen la suma, resta, etc.

Espero que esto aclare el propósito de las clases de servicio en la resolución de la tarea actual.

Implementación del servicio

Nuestro siguiente paso es mostrar explícitamente que esta clase implementa la interfaz TaskQueueService.

Para lograr esto, utilizamos la palabra clave implements seguida del nombre de la interfaz. Esto asegura que nuestra clase herede el comportamiento definido por la interfaz.

Dado que las interfaces solo proporcionan declaraciones de métodos, se deben sobrescribir e implementar estos métodos en nuestra clase.

Ahora, en nuestra clase, se muestran todos los métodos que deben ser sobrescritos. ¡Procedamos a hacerlo!

TaskQueueServiceImpl.java

TaskQueueServiceImpl.java

copy
1234567891011121314151617181920212223242526
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import codefinity.taskManager.TaskQueueService; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl implements TaskQueueService { private Queue<Task> taskQueue = new LinkedList<>(); @Override public void addTask(Task task) { taskQueue.offer(task); } @Override public Task getNextTask() { return taskQueue.poll(); } @Override public boolean isEmpty() { return taskQueue.isEmpty(); } }

En nuestro caso, no se realizó nada demasiado complicado. Simplemente utilizamos los métodos de la clase Queue para implementar correctamente nuestros métodos. Así, una estructura de datos como una cola facilita la vida a todos los programadores de Java.

Utilizamos el método offer() para agregar, el método poll() para eliminar y el método isEmpty() para comprobar si la cola está vacía.

Ahora es tu turno de participar en la resolución de este problema. Deberás implementar una clase de servicio, cuya interfaz crearemos juntos:

Main.java

Main.java

copy
12345
package codefinity.taskManager; public interface TaskProcessorService { void processTasks(); }

Hemos creado una interfaz de servicio con un método: processTasks(), que, al ser invocado, debe comenzar a ejecutar todas las tareas hasta que la lista de tareas esté vacía. Este método representa a un usuario comenzando a realizar tareas.

Tarea

La tarea consiste en escribir una clase TaskProcessorServiceImpl que debe implementar la interfaz TaskProcessorService. Esta clase debe tener un método para procesar todas las tareas, lo que significa que debe utilizar métodos del servicio TaskQueueService. Se puede utilizar composición creando una instancia de esta clase dentro de la clase que se necesita implementar, por ejemplo:

Main.java

Main.java

copy
1234567
package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.TaskQueueService; public class TaskProcessorServiceImpl { TaskQueueService taskQueueService = new TaskQueueServiceImpl(); }

En general, ya hay una composición preparada en la parte superior para tu tarea. A continuación, solo necesitas implementar un método utilizando una instancia de esta clase.

Después de eso, debes crear un constructor que inicialice este objeto de la clase taskQueueService.

De esta manera, podrás utilizar los métodos de este objeto. También es evidente que, para el procesamiento de tareas, necesitas pasar la cola con la que trabajará el taskProcessor.

El resto de la tarea queda a tu cargo. Se proporcionarán pistas en el archivo README.md. Una vez que tu solución esté lista, haz clic en el botón "Run Tests", y las pruebas unitarias que he escrito comprobarán tu solución.

  1. Primero, debes utilizar composición y crear una instancia de la clase TaskQueue. Luego, también añade su inicialización en el constructor.
  2. A continuación, implementa la interfaz TaskProcessorImpl y sobrescribe sus métodos.
  3. En la implementación de la interfaz, utiliza un bucle while con el método isEmpty() como condición.
  4. Dentro del bucle while, utiliza el método taskQueueService.getNextTask(), indicando que la tarea está completada. Muestra información en pantalla usando System.out.println() - "Processing Task: " + task.
  5. Cuando el bucle termine su trabajo, muestra en pantalla "All tasks processed.".
  6. Ejecuta las pruebas y verifica la corrección de tu solución.
package codefinity.taskManager.taskManagerImpl;

import codefinity.taskManager.Task;
import codefinity.taskManager.TaskProcessorService;
import codefinity.taskManager.TaskQueueService;

public class TaskProcessorServiceImpl implements TaskProcessorService {
    private final TaskQueueService taskQueueImpl;

    public TaskProcessorServiceImpl(TaskQueueService taskQueueImpl) {
        this.taskQueueImpl = taskQueueImpl;
    }

    @Override
    public void processTasks() {
        while (!taskQueueImpl.isEmpty()) {
            Task task = taskQueueImpl.getNextTask();
            System.out.println("Processing Task: " + task + ";");
        }
        System.out.println("All tasks processed successfully.");
    }
}
¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 2. Capítulo 3
some-alt