Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Apprendre Défi : Implémentation d’un Service TaskManager | Structures de Données Avancées en Java
Practice
Projects
Quizzes & Challenges
Quizzes
Challenges
/
Structures de Données Java

bookDéfi : Implémentation d’un Service TaskManager

Pratique

C'est le moment de pratiquer. L'objectif est de développer un service TaskManager permettant de suivre vos tâches.

Avec ce service, l'utilisateur peut ajouter des tâches, se les attribuer, puis les terminer dans un ordre séquentiel.

Commençons ensemble à travailler sur cette tâche, puis vous poursuivrez individuellement.

Mais d'abord, il est nécessaire de créer le modèle de tâche. Création d'une classe Task :

Main.java

Main.java

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

La classe Task contient trois attributs : id, name et description. Chaque tâche doit posséder un nom et une description, et id est un attribut nécessaire pour toute structure de données.

Comment accéderiez-vous autrement aux éléments ? Les attributs sont également protégés par le modificateur d'accès private car il n'est pas souhaitable que d'autres classes aient un accès direct aux champs de cette classe, sauf via le constructeur ou les accesseurs.

Implémentons maintenant ces accesseurs et le constructeur. Cela peut être facilement réalisé en utilisant la combinaison Control + Return sur un MacBook ou Alt + Ins sur Windows.

Après les opérations effectuées, vous disposez de la classe Task suivante :

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 + '\'' + '}'; } }

Services

Vous allez disposer d’un service de tableau de tâches très simplifié. Implémentez donc un service permettant d’ajouter des tâches, de les marquer comme terminées et de vérifier la présence de tâches dans la file d’attente.

Appelons cette classe TaskQueueService. Pour commencer, il est nécessaire de définir une interface regroupant ces opérations :

TaskQueueService.java

TaskQueueService.java

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

Cette interface définit 3 méthodes que les classes d’implémentation doivent implémenter. Ces méthodes incluent l’ajout d’une tâche, le passage à la tâche suivante (ce qui implique que l’utilisateur a déjà terminé la tâche précédente), ainsi qu’une méthode pour vérifier la présence de tâches dans la file d’attente.

Parfait, créons maintenant une classe d’implémentation qui va surcharger et implémenter l’ensemble de ces méthodes :

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<>(); }

Nous créons un attribut privé qui sera utilisé uniquement au sein de cette classe de service.

Il convient de faire une petite digression pour aborder les classes de service, qui jouent un rôle clé en POO.

Que sont les classes de service ?

Les classes de service sont conçues pour effectuer des opérations spécifiques. Elles héritent d'interfaces de service et implémentent leurs méthodes. Cette approche améliore la maintenabilité et la scalabilité du code tout en respectant les principes SOLID, que vous étudierez dans un cours séparé.

Pour l'instant, il est essentiel de comprendre que les classes de service existent uniquement pour effectuer des opérations sur d'autres objets.

Par exemple, Si vous écrivez une calculatrice, vous aurez une classe séparée qui stockera la valeur du nombre sur lequel vous opérez. Les opérations réelles seront effectuées à l'aide d'une classe de service où l'addition, la soustraction, etc. sont définies.

J'espère que cela clarifie l'objectif des classes de service dans la résolution de cette tâche.

Implémentation du service

L'étape suivante consiste à montrer explicitement que cette classe implémente l'interface TaskQueueService.

Pour cela, on utilise le mot-clé implements suivi du nom de l'interface. Cela garantit que notre classe hérite du comportement défini par l'interface.

Puisque les interfaces ne fournissent que des déclarations de méthodes, il est nécessaire de surcharger et d'implémenter ces méthodes dans notre classe.

À présent, dans notre classe, toutes les méthodes qui doivent être redéfinies sont affichées. Passons à leur implémentation !

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(); } }

Dans notre cas, rien de particulièrement complexe n'a été réalisé. Nous avons simplement utilisé les méthodes de la classe Queue pour implémenter correctement nos méthodes. Ainsi, une structure de données telle qu'une file facilite la vie de tous les programmeurs Java.

Nous utilisons la méthode offer() pour l'ajout, la méthode poll() pour la suppression, et la méthode isEmpty() pour vérifier si la file est vide.

C'est à vous de jouer pour résoudre ce problème. Vous devrez implémenter une classe de service, dont nous allons créer l'interface ensemble :

Main.java

Main.java

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

Nous avons créé une interface de service avec une méthode : processTasks(), qui, lorsqu'elle est appelée, doit commencer à exécuter toutes les tâches jusqu'à ce que la liste des tâches soit vide. Cette méthode représente un utilisateur commençant à effectuer des tâches.

Tâche

Votre tâche consiste à écrire une classe TaskProcessorServiceImpl qui doit implémenter l'interface TaskProcessorService. Cette classe doit comporter une méthode pour traiter toutes les tâches, c'est-à-dire qu'elle doit utiliser les méthodes du service TaskQueueService. Vous pouvez utiliser la composition en créant une instance de cette classe à l'intérieur de la classe que vous devez implémenter, par exemple :

Main.java

Main.java

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

En général, une composition déjà préparée se trouve en haut pour votre tâche. Ensuite, il suffit d’implémenter une méthode en utilisant une instance de cette classe.

Après cela, il est nécessaire de créer un constructeur qui initialisera cet objet de la classe taskQueueService.

De cette manière, il sera possible d’utiliser les méthodes de cet objet. Il est également évident que, pour le traitement des tâches, il faut transmettre la file d’attente avec laquelle le taskProcessor va travailler.

Le reste de la tâche vous revient. Des indices seront fournis dans le fichier README.md. Une fois votre solution prête, cliquez sur le bouton « Run Tests », et les tests unitaires que j’ai écrits vérifieront votre solution.

  1. Tout d’abord, utiliser la composition et créer une instance de la classe TaskQueue. Ensuite, ajouter également son initialisation dans le constructeur.
  2. Ensuite, implémenter l’interface TaskProcessorImpl et redéfinir ses méthodes.
  3. Dans l’implémentation de l’interface, utiliser une boucle while avec la méthode isEmpty() comme condition.
  4. À l’intérieur de la boucle while, utiliser la méthode taskQueueService.getNextTask(), en indiquant que la tâche est terminée. Afficher les informations à l’écran avec System.out.println() : "Processing Task: " + task.
  5. Lorsque la boucle termine son exécution, afficher "All tasks processed." à l’écran.
  6. Exécuter les tests et vérifier la validité de votre solution.
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.");
    }
}
Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 2. Chapitre 3

Demandez à l'IA

expand

Demandez à l'IA

ChatGPT

Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion

bookDéfi : Implémentation d’un Service TaskManager

Glissez pour afficher le menu

Pratique

C'est le moment de pratiquer. L'objectif est de développer un service TaskManager permettant de suivre vos tâches.

Avec ce service, l'utilisateur peut ajouter des tâches, se les attribuer, puis les terminer dans un ordre séquentiel.

Commençons ensemble à travailler sur cette tâche, puis vous poursuivrez individuellement.

Mais d'abord, il est nécessaire de créer le modèle de tâche. Création d'une classe Task :

Main.java

Main.java

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

La classe Task contient trois attributs : id, name et description. Chaque tâche doit posséder un nom et une description, et id est un attribut nécessaire pour toute structure de données.

Comment accéderiez-vous autrement aux éléments ? Les attributs sont également protégés par le modificateur d'accès private car il n'est pas souhaitable que d'autres classes aient un accès direct aux champs de cette classe, sauf via le constructeur ou les accesseurs.

Implémentons maintenant ces accesseurs et le constructeur. Cela peut être facilement réalisé en utilisant la combinaison Control + Return sur un MacBook ou Alt + Ins sur Windows.

Après les opérations effectuées, vous disposez de la classe Task suivante :

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 + '\'' + '}'; } }

Services

Vous allez disposer d’un service de tableau de tâches très simplifié. Implémentez donc un service permettant d’ajouter des tâches, de les marquer comme terminées et de vérifier la présence de tâches dans la file d’attente.

Appelons cette classe TaskQueueService. Pour commencer, il est nécessaire de définir une interface regroupant ces opérations :

TaskQueueService.java

TaskQueueService.java

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

Cette interface définit 3 méthodes que les classes d’implémentation doivent implémenter. Ces méthodes incluent l’ajout d’une tâche, le passage à la tâche suivante (ce qui implique que l’utilisateur a déjà terminé la tâche précédente), ainsi qu’une méthode pour vérifier la présence de tâches dans la file d’attente.

Parfait, créons maintenant une classe d’implémentation qui va surcharger et implémenter l’ensemble de ces méthodes :

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<>(); }

Nous créons un attribut privé qui sera utilisé uniquement au sein de cette classe de service.

Il convient de faire une petite digression pour aborder les classes de service, qui jouent un rôle clé en POO.

Que sont les classes de service ?

Les classes de service sont conçues pour effectuer des opérations spécifiques. Elles héritent d'interfaces de service et implémentent leurs méthodes. Cette approche améliore la maintenabilité et la scalabilité du code tout en respectant les principes SOLID, que vous étudierez dans un cours séparé.

Pour l'instant, il est essentiel de comprendre que les classes de service existent uniquement pour effectuer des opérations sur d'autres objets.

Par exemple, Si vous écrivez une calculatrice, vous aurez une classe séparée qui stockera la valeur du nombre sur lequel vous opérez. Les opérations réelles seront effectuées à l'aide d'une classe de service où l'addition, la soustraction, etc. sont définies.

J'espère que cela clarifie l'objectif des classes de service dans la résolution de cette tâche.

Implémentation du service

L'étape suivante consiste à montrer explicitement que cette classe implémente l'interface TaskQueueService.

Pour cela, on utilise le mot-clé implements suivi du nom de l'interface. Cela garantit que notre classe hérite du comportement défini par l'interface.

Puisque les interfaces ne fournissent que des déclarations de méthodes, il est nécessaire de surcharger et d'implémenter ces méthodes dans notre classe.

À présent, dans notre classe, toutes les méthodes qui doivent être redéfinies sont affichées. Passons à leur implémentation !

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(); } }

Dans notre cas, rien de particulièrement complexe n'a été réalisé. Nous avons simplement utilisé les méthodes de la classe Queue pour implémenter correctement nos méthodes. Ainsi, une structure de données telle qu'une file facilite la vie de tous les programmeurs Java.

Nous utilisons la méthode offer() pour l'ajout, la méthode poll() pour la suppression, et la méthode isEmpty() pour vérifier si la file est vide.

C'est à vous de jouer pour résoudre ce problème. Vous devrez implémenter une classe de service, dont nous allons créer l'interface ensemble :

Main.java

Main.java

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

Nous avons créé une interface de service avec une méthode : processTasks(), qui, lorsqu'elle est appelée, doit commencer à exécuter toutes les tâches jusqu'à ce que la liste des tâches soit vide. Cette méthode représente un utilisateur commençant à effectuer des tâches.

Tâche

Votre tâche consiste à écrire une classe TaskProcessorServiceImpl qui doit implémenter l'interface TaskProcessorService. Cette classe doit comporter une méthode pour traiter toutes les tâches, c'est-à-dire qu'elle doit utiliser les méthodes du service TaskQueueService. Vous pouvez utiliser la composition en créant une instance de cette classe à l'intérieur de la classe que vous devez implémenter, par exemple :

Main.java

Main.java

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

En général, une composition déjà préparée se trouve en haut pour votre tâche. Ensuite, il suffit d’implémenter une méthode en utilisant une instance de cette classe.

Après cela, il est nécessaire de créer un constructeur qui initialisera cet objet de la classe taskQueueService.

De cette manière, il sera possible d’utiliser les méthodes de cet objet. Il est également évident que, pour le traitement des tâches, il faut transmettre la file d’attente avec laquelle le taskProcessor va travailler.

Le reste de la tâche vous revient. Des indices seront fournis dans le fichier README.md. Une fois votre solution prête, cliquez sur le bouton « Run Tests », et les tests unitaires que j’ai écrits vérifieront votre solution.

  1. Tout d’abord, utiliser la composition et créer une instance de la classe TaskQueue. Ensuite, ajouter également son initialisation dans le constructeur.
  2. Ensuite, implémenter l’interface TaskProcessorImpl et redéfinir ses méthodes.
  3. Dans l’implémentation de l’interface, utiliser une boucle while avec la méthode isEmpty() comme condition.
  4. À l’intérieur de la boucle while, utiliser la méthode taskQueueService.getNextTask(), en indiquant que la tâche est terminée. Afficher les informations à l’écran avec System.out.println() : "Processing Task: " + task.
  5. Lorsque la boucle termine son exécution, afficher "All tasks processed." à l’écran.
  6. Exécuter les tests et vérifier la validité de votre solution.
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.");
    }
}
Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 2. Chapitre 3
some-alt