Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Impara Sfida: Implementazione di un Servizio TaskManager | Strutture Dati Avanzate in Java
Practice
Projects
Quizzes & Challenges
Quizzes
Challenges
/
Strutture Dati Java

bookSfida: Implementazione di un Servizio TaskManager

Pratica

È il momento di esercitarsi. Hai il compito di scrivere un servizio TaskManager che terrà traccia delle tue attività.

Con questo servizio, l'utente può aggiungere attività, assegnarle a sé stesso e poi completarle in ordine sequenziale.

Iniziamo a lavorare su questo compito insieme, poi continuerai da solo.

Ma prima, è necessario creare il modello di attività stesso. Creiamo una classe Task:

Main.java

Main.java

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

La classe Task contiene tre attributi: id, name e description. Ogni task deve avere un name e description, e id è un attributo necessario per qualsiasi struttura dati.

Come si accederebbero altrimenti agli elementi? Gli attributi sono inoltre protetti dal modificatore di accesso private perché non si desidera che altre classi abbiano accesso diretto ai campi di questa classe, se non tramite il costruttore o i metodi getter.

Ora, implementiamo questi getter e il costruttore. Questo può essere facilmente fatto utilizzando la combinazione di tasti Control + Return su MacBook o Alt + Ins su Windows.

Dopo le operazioni eseguite, si ottiene la seguente classe 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 + '\'' + '}'; } }

Servizi

Avrai a disposizione un servizio di task board molto semplificato, quindi implementiamo un servizio che possa aggiungere task, contrassegnarli come completati e verificare se ci sono task nella coda.

Chiamiamo questa classe TaskQueueService. Per iniziare, è necessario definire un'interfaccia con queste operazioni:

TaskQueueService.java

TaskQueueService.java

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

Questa interfaccia definisce 3 metodi che le classi di implementazione devono implementare. Questi metodi includono aggiunta di un task, passaggio al task successivo (implicando che l'utente abbia già completato il task precedente) e un metodo per verificare se ci sono task nella coda.

Ottimo, ora creiamo una classe di implementazione che eseguirà l'override e implementerà tutti questi metodi:

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

Creiamo un attributo privato che verrà utilizzato solo all'interno di questa classe di servizio.

Vale la pena fare una piccola digressione per parlare delle classi di servizio, che svolgono un ruolo chiave nella OOP.

Cosa sono le classi di servizio?

Le classi di servizio sono progettate per eseguire operazioni specifiche. Ereditano dalle interfacce di servizio e implementano i loro metodi. Questo approccio migliora la manutenibilità e la scalabilità del codice, seguendo i principi SOLID, che verranno approfonditi in un corso separato.

Per ora, è fondamentale comprendere che le classi di servizio esistono esclusivamente per eseguire operazioni su altri oggetti.

Ad esempio, se si scrive una calcolatrice, si avrà una classe separata che memorizza il valore del numero su cui si opera. Le operazioni effettive verranno eseguite utilizzando una classe di servizio in cui sono definite somma, sottrazione e così via.

Spero che questo chiarisca lo scopo delle classi di servizio nella risoluzione del compito proposto.

Implementazione del servizio

Il prossimo passo consiste nel mostrare esplicitamente che questa classe implementa l'interfaccia TaskQueueService.

Per ottenere questo risultato, si utilizza la parola chiave implements seguita dal nome dell'interfaccia. Questo garantisce che la nostra classe erediti il comportamento definito dall'interfaccia.

Poiché le interfacce forniscono solo le dichiarazioni dei metodi, è necessario sovrascrivere e implementare questi metodi nella nostra classe.

Ora, nella nostra classe, sono mostrati tutti i metodi che devono essere sovrascritti. Procediamo con l'implementazione!

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

Nel nostro caso, non è stato fatto nulla di particolarmente complicato. Abbiamo semplicemente utilizzato i metodi della classe Queue per implementare correttamente i nostri metodi. In questo modo, una struttura dati come una coda semplifica la vita a tutti i programmatori Java.

Utilizziamo il metodo offer() per l'aggiunta, il metodo poll() per la rimozione e il metodo isEmpty() per verificare se la coda è vuota.

Ora tocca a te svolgere un ruolo nella risoluzione di questo problema. Dovrai implementare una classe di servizio, la cui interfaccia creeremo insieme:

Main.java

Main.java

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

Abbiamo creato un'interfaccia service con un solo metodo: processTasks(), che, quando viene invocato, deve avviare l'esecuzione di tutti i task fino a svuotare la lista dei task. Questo metodo rappresenta l'avvio dell'esecuzione dei task da parte dell'utente.

Compito

Il compito consiste nello scrivere una classe TaskProcessorServiceImpl che implementi l'interfaccia TaskProcessorService. Questa classe deve avere un metodo per processare tutti i task, utilizzando i metodi forniti dal servizio TaskQueueService. È possibile utilizzare la composizione creando un'istanza di questa classe all'interno della classe da implementare, ad esempio:

Main.java

Main.java

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

In generale, è già presente una composizione preparata in alto per il tuo compito. Successivamente, è sufficiente implementare un metodo utilizzando un'istanza di questa classe.

Dopo di ciò, è necessario creare un costruttore che inizializzi questo oggetto della classe taskQueueService.

In questo modo, sarà possibile utilizzare i metodi di questo oggetto. È inoltre evidente che, per l'elaborazione dei task, è necessario passare la coda con cui lavorerà il taskProcessor.

Il resto del compito è lasciato a te. Suggerimenti saranno forniti nel file README.md. Una volta che la tua soluzione è pronta, clicca sul pulsante "Run Tests" e i test unitari che ho scritto verificheranno la tua soluzione.

  1. Per prima cosa, utilizzare la composizione e creare un'istanza della classe TaskQueue. Quindi, aggiungere anche la sua inizializzazione nel costruttore.
  2. Successivamente, implementare l'interfaccia TaskProcessorImpl e sovrascrivere i suoi metodi.
  3. Nell'implementazione dell'interfaccia, utilizzare un ciclo while con il metodo isEmpty() come condizione.
  4. All'interno del ciclo while, utilizzare il metodo taskQueueService.getNextTask(), indicando che il task è stato completato. Stampare le informazioni a schermo utilizzando System.out.println() - "Processing Task: " + task.
  5. Quando il ciclo termina, stampare a schermo "All tasks processed.".
  6. Eseguire i test e verificare la correttezza della soluzione.
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.");
    }
}
Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 2. Capitolo 3

Chieda ad AI

expand

Chieda ad AI

ChatGPT

Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione

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?

bookSfida: Implementazione di un Servizio TaskManager

Scorri per mostrare il menu

Pratica

È il momento di esercitarsi. Hai il compito di scrivere un servizio TaskManager che terrà traccia delle tue attività.

Con questo servizio, l'utente può aggiungere attività, assegnarle a sé stesso e poi completarle in ordine sequenziale.

Iniziamo a lavorare su questo compito insieme, poi continuerai da solo.

Ma prima, è necessario creare il modello di attività stesso. Creiamo una classe Task:

Main.java

Main.java

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

La classe Task contiene tre attributi: id, name e description. Ogni task deve avere un name e description, e id è un attributo necessario per qualsiasi struttura dati.

Come si accederebbero altrimenti agli elementi? Gli attributi sono inoltre protetti dal modificatore di accesso private perché non si desidera che altre classi abbiano accesso diretto ai campi di questa classe, se non tramite il costruttore o i metodi getter.

Ora, implementiamo questi getter e il costruttore. Questo può essere facilmente fatto utilizzando la combinazione di tasti Control + Return su MacBook o Alt + Ins su Windows.

Dopo le operazioni eseguite, si ottiene la seguente classe 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 + '\'' + '}'; } }

Servizi

Avrai a disposizione un servizio di task board molto semplificato, quindi implementiamo un servizio che possa aggiungere task, contrassegnarli come completati e verificare se ci sono task nella coda.

Chiamiamo questa classe TaskQueueService. Per iniziare, è necessario definire un'interfaccia con queste operazioni:

TaskQueueService.java

TaskQueueService.java

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

Questa interfaccia definisce 3 metodi che le classi di implementazione devono implementare. Questi metodi includono aggiunta di un task, passaggio al task successivo (implicando che l'utente abbia già completato il task precedente) e un metodo per verificare se ci sono task nella coda.

Ottimo, ora creiamo una classe di implementazione che eseguirà l'override e implementerà tutti questi metodi:

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

Creiamo un attributo privato che verrà utilizzato solo all'interno di questa classe di servizio.

Vale la pena fare una piccola digressione per parlare delle classi di servizio, che svolgono un ruolo chiave nella OOP.

Cosa sono le classi di servizio?

Le classi di servizio sono progettate per eseguire operazioni specifiche. Ereditano dalle interfacce di servizio e implementano i loro metodi. Questo approccio migliora la manutenibilità e la scalabilità del codice, seguendo i principi SOLID, che verranno approfonditi in un corso separato.

Per ora, è fondamentale comprendere che le classi di servizio esistono esclusivamente per eseguire operazioni su altri oggetti.

Ad esempio, se si scrive una calcolatrice, si avrà una classe separata che memorizza il valore del numero su cui si opera. Le operazioni effettive verranno eseguite utilizzando una classe di servizio in cui sono definite somma, sottrazione e così via.

Spero che questo chiarisca lo scopo delle classi di servizio nella risoluzione del compito proposto.

Implementazione del servizio

Il prossimo passo consiste nel mostrare esplicitamente che questa classe implementa l'interfaccia TaskQueueService.

Per ottenere questo risultato, si utilizza la parola chiave implements seguita dal nome dell'interfaccia. Questo garantisce che la nostra classe erediti il comportamento definito dall'interfaccia.

Poiché le interfacce forniscono solo le dichiarazioni dei metodi, è necessario sovrascrivere e implementare questi metodi nella nostra classe.

Ora, nella nostra classe, sono mostrati tutti i metodi che devono essere sovrascritti. Procediamo con l'implementazione!

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

Nel nostro caso, non è stato fatto nulla di particolarmente complicato. Abbiamo semplicemente utilizzato i metodi della classe Queue per implementare correttamente i nostri metodi. In questo modo, una struttura dati come una coda semplifica la vita a tutti i programmatori Java.

Utilizziamo il metodo offer() per l'aggiunta, il metodo poll() per la rimozione e il metodo isEmpty() per verificare se la coda è vuota.

Ora tocca a te svolgere un ruolo nella risoluzione di questo problema. Dovrai implementare una classe di servizio, la cui interfaccia creeremo insieme:

Main.java

Main.java

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

Abbiamo creato un'interfaccia service con un solo metodo: processTasks(), che, quando viene invocato, deve avviare l'esecuzione di tutti i task fino a svuotare la lista dei task. Questo metodo rappresenta l'avvio dell'esecuzione dei task da parte dell'utente.

Compito

Il compito consiste nello scrivere una classe TaskProcessorServiceImpl che implementi l'interfaccia TaskProcessorService. Questa classe deve avere un metodo per processare tutti i task, utilizzando i metodi forniti dal servizio TaskQueueService. È possibile utilizzare la composizione creando un'istanza di questa classe all'interno della classe da implementare, ad esempio:

Main.java

Main.java

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

In generale, è già presente una composizione preparata in alto per il tuo compito. Successivamente, è sufficiente implementare un metodo utilizzando un'istanza di questa classe.

Dopo di ciò, è necessario creare un costruttore che inizializzi questo oggetto della classe taskQueueService.

In questo modo, sarà possibile utilizzare i metodi di questo oggetto. È inoltre evidente che, per l'elaborazione dei task, è necessario passare la coda con cui lavorerà il taskProcessor.

Il resto del compito è lasciato a te. Suggerimenti saranno forniti nel file README.md. Una volta che la tua soluzione è pronta, clicca sul pulsante "Run Tests" e i test unitari che ho scritto verificheranno la tua soluzione.

  1. Per prima cosa, utilizzare la composizione e creare un'istanza della classe TaskQueue. Quindi, aggiungere anche la sua inizializzazione nel costruttore.
  2. Successivamente, implementare l'interfaccia TaskProcessorImpl e sovrascrivere i suoi metodi.
  3. Nell'implementazione dell'interfaccia, utilizzare un ciclo while con il metodo isEmpty() come condizione.
  4. All'interno del ciclo while, utilizzare il metodo taskQueueService.getNextTask(), indicando che il task è stato completato. Stampare le informazioni a schermo utilizzando System.out.println() - "Processing Task: " + task.
  5. Quando il ciclo termina, stampare a schermo "All tasks processed.".
  6. Eseguire i test e verificare la correttezza della soluzione.
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.");
    }
}
Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 2. Capitolo 3
some-alt