Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Leer Uitdaging: Implementatie van een TaskManager-service | Geavanceerde Datastructuren in Java
Java Datastructuren

bookUitdaging: Implementatie van een TaskManager-service

Oefening

Het is tijd om te oefenen. De opdracht is het schrijven van een TaskManager service die je taken bijhoudt.

Met deze service kan de gebruiker taken toevoegen, deze aan zichzelf toewijzen en ze vervolgens in een sequentiële volgorde afronden.

Laten we samen beginnen aan deze opdracht, waarna je zelfstandig verdergaat.

Maar eerst moet je het taakmodel zelf maken. Laten we een Task-klasse aanmaken:

Main.java

Main.java

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

De Task-klasse bevat drie attributen: id, name en description. Elke taak moet een naam en beschrijving hebben, en id is een noodzakelijk attribuut voor elke datastructuur.

Hoe zou je anders de elementen benaderen? De attributen zijn ook beveiligd door de private access modifier omdat je niet wilt dat andere klassen directe toegang hebben tot de velden van deze klasse, behalve via de constructor of getters.

Laten we nu deze getters en de constructor implementeren. Dit kan eenvoudig worden gedaan met de combinatie Control + Return op een MacBook of Alt + Ins op een Windows.

Na de uitgevoerde bewerkingen heb je de volgende Task-klasse:

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

Je krijgt een sterk vereenvoudigde taakbordservice, dus laten we een service implementeren die taken kan toevoegen, markeren als voltooid en controleren of er taken in de wachtrij staan.

Noem deze klasse TaskQueueService. Om te beginnen moeten we een interface definiëren met deze taken:

TaskQueueService.java

TaskQueueService.java

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

Deze interface definieert 3 methoden die implementatieklassen moeten implementeren. Deze methoden omvatten het toevoegen van een taak, doorgaan naar de volgende taak (waarbij wordt aangenomen dat de gebruiker de vorige taak al heeft voltooid), en een methode om te controleren of er taken in de wachtrij staan.

Prima, laten we nu een implementatieklasse maken die al deze methoden zal overschrijven en implementeren:

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

We creëren een privé-attribuut dat uitsluitend binnen deze serviceklasse wordt gebruikt.

Het is de moeite waard om een korte uitweiding te maken over serviceklassen, die een sleutelrol spelen in OOP.

Wat zijn serviceklassen?

Serviceklassen zijn ontworpen om specifieke bewerkingen uit te voeren. Ze erven van service-interfaces en implementeren hun methoden. Deze aanpak verbetert de onderhoudbaarheid en schaalbaarheid van de code en volgt de SOLID-principes, die je in een aparte cursus verder zult verkennen.

Voor nu is het belangrijk te begrijpen dat serviceklassen uitsluitend bestaan om bewerkingen op andere objecten uit te voeren.

Bijvoorbeeld, Als je een rekenmachine schrijft, heb je een aparte klasse die de waarde van het getal waarop je werkt opslaat. De daadwerkelijke bewerkingen worden uitgevoerd met behulp van een serviceklasse waarin optellen, aftrekken, enzovoorts zijn gedefinieerd.

Hopelijk verduidelijkt dit het doel van serviceklassen bij het oplossen van deze taak.

Service-implementatie

Onze volgende stap is om expliciet aan te geven dat deze klasse de TaskQueueService-interface implementeert.

Om dit te bereiken, gebruiken we het implements-sleutelwoord gevolgd door de naam van de interface. Dit zorgt ervoor dat onze klasse het gedrag erft dat door de interface is gedefinieerd.

Aangezien interfaces alleen methodeverklaringen bieden, moet je deze methoden overriden en implementeren in onze klasse.

Nu worden in onze klasse alle methoden weergegeven die moeten worden overschreven. Laten we dit uitvoeren!

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

In ons geval is er niets bijzonder ingewikkelds gedaan. We hebben eenvoudigweg de methoden van de Queue-klasse gebruikt om onze methoden correct te implementeren. Zo maakt een datastructuur zoals een queue het leven van alle Java-programmeurs eenvoudiger.

We gebruiken de methode offer() om toe te voegen, de methode poll() om te verwijderen en de methode isEmpty() om te controleren of de queue leeg is.

Nu is het jouw beurt om een rol te spelen bij het oplossen van dit probleem. Je moet een serviceklasse implementeren, waarvan we samen het interface zullen opstellen:

Main.java

Main.java

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

We hebben een service-interface gemaakt met één methode: processTasks(), die, wanneer aangeroepen, alle taken moet uitvoeren totdat de takenlijst leeg is. Deze methode vertegenwoordigt een gebruiker die begint met het uitvoeren van taken.

Taak

Je taak is om een klasse TaskProcessorServiceImpl te schrijven die de interface TaskProcessorService implementeert. Deze klasse moet een methode bevatten om alle taken te verwerken, wat betekent dat je methoden van de service TaskQueueService moet gebruiken. Je kunt compositie toepassen door een instantie van deze klasse aan te maken binnen de klasse die je moet implementeren, bijvoorbeeld:

Main.java

Main.java

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

In het algemeen is er al een voorbereide compositie bovenaan voor jouw taak. Vervolgens hoef je alleen nog één methode te implementeren met behulp van een instantie van deze klasse.

Daarna dien je een constructor te maken die dit object van de klasse taskQueueService initialiseert.

Op deze manier kun je de methoden van dit object gebruiken. Het is ook duidelijk dat je, voor de verwerking van taken, de queue moet doorgeven waarmee de taskProcessor zal werken.

De rest van de opdracht is aan jou. Hints worden gegeven in het README.md-bestand. Zodra je oplossing klaar is, klik je op de knop "Run Tests", en de unittests die ik heb geschreven zullen je oplossing controleren.

  1. Gebruik eerst compositie en maak een instantie van de klasse TaskQueue. Voeg vervolgens ook de initialisatie ervan toe in de constructor.
  2. Implementeer daarna de interface TaskProcessorImpl en override de methoden ervan.
  3. Gebruik in de implementatie van de interface een while-lus met de methode isEmpty() als voorwaarde.
  4. Gebruik binnen de while-lus de methode taskQueueService.getNextTask(), waarmee wordt aangegeven dat de taak is voltooid. Geef informatie weer op het scherm met System.out.println() - "Processing Task: " + task.
  5. Wanneer de lus klaar is, geef dan "All tasks processed." weer op het scherm.
  6. Voer de tests uit en controleer de juistheid van je oplossing.
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.");
    }
}
Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 2. Hoofdstuk 3

Vraag AI

expand

Vraag AI

ChatGPT

Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.

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?

bookUitdaging: Implementatie van een TaskManager-service

Veeg om het menu te tonen

Oefening

Het is tijd om te oefenen. De opdracht is het schrijven van een TaskManager service die je taken bijhoudt.

Met deze service kan de gebruiker taken toevoegen, deze aan zichzelf toewijzen en ze vervolgens in een sequentiële volgorde afronden.

Laten we samen beginnen aan deze opdracht, waarna je zelfstandig verdergaat.

Maar eerst moet je het taakmodel zelf maken. Laten we een Task-klasse aanmaken:

Main.java

Main.java

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

De Task-klasse bevat drie attributen: id, name en description. Elke taak moet een naam en beschrijving hebben, en id is een noodzakelijk attribuut voor elke datastructuur.

Hoe zou je anders de elementen benaderen? De attributen zijn ook beveiligd door de private access modifier omdat je niet wilt dat andere klassen directe toegang hebben tot de velden van deze klasse, behalve via de constructor of getters.

Laten we nu deze getters en de constructor implementeren. Dit kan eenvoudig worden gedaan met de combinatie Control + Return op een MacBook of Alt + Ins op een Windows.

Na de uitgevoerde bewerkingen heb je de volgende Task-klasse:

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

Je krijgt een sterk vereenvoudigde taakbordservice, dus laten we een service implementeren die taken kan toevoegen, markeren als voltooid en controleren of er taken in de wachtrij staan.

Noem deze klasse TaskQueueService. Om te beginnen moeten we een interface definiëren met deze taken:

TaskQueueService.java

TaskQueueService.java

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

Deze interface definieert 3 methoden die implementatieklassen moeten implementeren. Deze methoden omvatten het toevoegen van een taak, doorgaan naar de volgende taak (waarbij wordt aangenomen dat de gebruiker de vorige taak al heeft voltooid), en een methode om te controleren of er taken in de wachtrij staan.

Prima, laten we nu een implementatieklasse maken die al deze methoden zal overschrijven en implementeren:

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

We creëren een privé-attribuut dat uitsluitend binnen deze serviceklasse wordt gebruikt.

Het is de moeite waard om een korte uitweiding te maken over serviceklassen, die een sleutelrol spelen in OOP.

Wat zijn serviceklassen?

Serviceklassen zijn ontworpen om specifieke bewerkingen uit te voeren. Ze erven van service-interfaces en implementeren hun methoden. Deze aanpak verbetert de onderhoudbaarheid en schaalbaarheid van de code en volgt de SOLID-principes, die je in een aparte cursus verder zult verkennen.

Voor nu is het belangrijk te begrijpen dat serviceklassen uitsluitend bestaan om bewerkingen op andere objecten uit te voeren.

Bijvoorbeeld, Als je een rekenmachine schrijft, heb je een aparte klasse die de waarde van het getal waarop je werkt opslaat. De daadwerkelijke bewerkingen worden uitgevoerd met behulp van een serviceklasse waarin optellen, aftrekken, enzovoorts zijn gedefinieerd.

Hopelijk verduidelijkt dit het doel van serviceklassen bij het oplossen van deze taak.

Service-implementatie

Onze volgende stap is om expliciet aan te geven dat deze klasse de TaskQueueService-interface implementeert.

Om dit te bereiken, gebruiken we het implements-sleutelwoord gevolgd door de naam van de interface. Dit zorgt ervoor dat onze klasse het gedrag erft dat door de interface is gedefinieerd.

Aangezien interfaces alleen methodeverklaringen bieden, moet je deze methoden overriden en implementeren in onze klasse.

Nu worden in onze klasse alle methoden weergegeven die moeten worden overschreven. Laten we dit uitvoeren!

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

In ons geval is er niets bijzonder ingewikkelds gedaan. We hebben eenvoudigweg de methoden van de Queue-klasse gebruikt om onze methoden correct te implementeren. Zo maakt een datastructuur zoals een queue het leven van alle Java-programmeurs eenvoudiger.

We gebruiken de methode offer() om toe te voegen, de methode poll() om te verwijderen en de methode isEmpty() om te controleren of de queue leeg is.

Nu is het jouw beurt om een rol te spelen bij het oplossen van dit probleem. Je moet een serviceklasse implementeren, waarvan we samen het interface zullen opstellen:

Main.java

Main.java

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

We hebben een service-interface gemaakt met één methode: processTasks(), die, wanneer aangeroepen, alle taken moet uitvoeren totdat de takenlijst leeg is. Deze methode vertegenwoordigt een gebruiker die begint met het uitvoeren van taken.

Taak

Je taak is om een klasse TaskProcessorServiceImpl te schrijven die de interface TaskProcessorService implementeert. Deze klasse moet een methode bevatten om alle taken te verwerken, wat betekent dat je methoden van de service TaskQueueService moet gebruiken. Je kunt compositie toepassen door een instantie van deze klasse aan te maken binnen de klasse die je moet implementeren, bijvoorbeeld:

Main.java

Main.java

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

In het algemeen is er al een voorbereide compositie bovenaan voor jouw taak. Vervolgens hoef je alleen nog één methode te implementeren met behulp van een instantie van deze klasse.

Daarna dien je een constructor te maken die dit object van de klasse taskQueueService initialiseert.

Op deze manier kun je de methoden van dit object gebruiken. Het is ook duidelijk dat je, voor de verwerking van taken, de queue moet doorgeven waarmee de taskProcessor zal werken.

De rest van de opdracht is aan jou. Hints worden gegeven in het README.md-bestand. Zodra je oplossing klaar is, klik je op de knop "Run Tests", en de unittests die ik heb geschreven zullen je oplossing controleren.

  1. Gebruik eerst compositie en maak een instantie van de klasse TaskQueue. Voeg vervolgens ook de initialisatie ervan toe in de constructor.
  2. Implementeer daarna de interface TaskProcessorImpl en override de methoden ervan.
  3. Gebruik in de implementatie van de interface een while-lus met de methode isEmpty() als voorwaarde.
  4. Gebruik binnen de while-lus de methode taskQueueService.getNextTask(), waarmee wordt aangegeven dat de taak is voltooid. Geef informatie weer op het scherm met System.out.println() - "Processing Task: " + task.
  5. Wanneer de lus klaar is, geef dan "All tasks processed." weer op het scherm.
  6. Voer de tests uit en controleer de juistheid van je oplossing.
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.");
    }
}
Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 2. Hoofdstuk 3
some-alt