Herausforderung: Implementierung eines Taskmanager-Dienstes
Übung
Es ist Zeit zum Üben. Die Aufgabe besteht darin, einen TaskManager-Dienst zu implementieren, der Aufgaben verwaltet.
Mit diesem Dienst kann der Benutzer Aufgaben hinzufügen, sie sich zuweisen und sie anschließend in einer festgelegten Reihenfolge erledigen.
Lassen Sie uns gemeinsam mit dieser Aufgabe beginnen; anschließend führen Sie sie eigenständig fort.
Zunächst muss das Task-Modell selbst erstellt werden. Erstellen Sie eine Task-Klasse:
Main.java
12345public class Task { private int id; private String name; private String description; }
Die Task-Klasse enthält drei Attribute: id, name und description. Jede Aufgabe muss einen Namen und eine Beschreibung besitzen, und id ist ein notwendiges Attribut für jede Datenstruktur.
Wie sonst könnten Sie auf die Elemente zugreifen?
Die Attribute sind außerdem durch den Zugriffsmodifizierer private geschützt, da andere Klassen keinen direkten Zugriff auf die Felder dieser Klasse haben sollen, außer über den Konstruktor oder Getter.
Nun implementieren wir diese Getter und den Konstruktor. Dies kann einfach durch die Kombination von Control + Return auf einem MacBook oder Alt + Ins unter Windows erledigt werden.
Nach den durchgeführten Operationen haben Sie die folgende Task-Klasse:
Task.java
12345678910111213141516171819202122232425262728293031323334package 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
Sie arbeiten mit einem stark vereinfachten Task-Board-Service. Implementieren Sie einen Service, der Aufgaben hinzufügt, sie als erledigt markiert und überprüft, ob Aufgaben in der Warteschlange vorhanden sind.
Nennen wir diese Klasse TaskQueueService.
Zunächst muss ein Interface mit diesen Aufgaben definiert werden:
TaskQueueService.java
123456789package codefinity.taskManager; public interface TaskQueueService { void addTask(Task task); Task getNextTask(); boolean isEmpty(); }
Dieses Interface definiert 3 Methoden, die von Implementierungsklassen umgesetzt werden müssen. Dazu gehören das Hinzufügen einer Aufgabe, das Wechseln zur nächsten Aufgabe (was voraussetzt, dass die vorherige Aufgabe bereits erledigt wurde), sowie eine Methode zur Überprüfung, ob Aufgaben in der Warteschlange vorhanden sind.
Sehr gut, erstellen wir nun eine Implementierungsklasse, die alle diese Methoden überschreibt und implementiert:
TaskQueueServiceImpl.java
12345678910package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl { private Queue<Task> taskQueue = new LinkedList<>(); }
Wir erstellen ein privates Attribut, das ausschließlich innerhalb dieser Serviceklasse verwendet wird.
Es lohnt sich, einen kurzen Exkurs zu machen, um über Serviceklassen zu sprechen, die eine Schlüsselrolle in der OOP spielen.
Was sind Serviceklassen?
Serviceklassen sind dafür konzipiert, spezifische Operationen auszuführen. Sie erben von Service-Interfaces und implementieren deren Methoden. Dieser Ansatz verbessert die Wartbarkeit und Skalierbarkeit des Codes und folgt den SOLID-Prinzipien, die Sie in einem separaten Kurs kennenlernen werden.
Für den Moment ist es wichtig zu verstehen, dass Serviceklassen ausschließlich dazu dienen, Operationen an anderen Objekten auszuführen.
Beispielsweise Wenn Sie einen Taschenrechner programmieren, gibt es eine separate Klasse, die den Wert der Zahl, mit der Sie arbeiten, speichert. Die eigentlichen Operationen werden mit einer Serviceklasse durchgeführt, in der Addition, Subtraktion usw. definiert sind.
Ich hoffe, dies verdeutlicht den Zweck von Serviceklassen bei der Lösung der aktuellen Aufgabe.
Service-Implementierung
Unser nächster Schritt ist es, explizit zu zeigen, dass diese Klasse das Interface TaskQueueService implementiert.
Dazu verwenden wir das Schlüsselwort implements gefolgt vom Namen des Interfaces. Dies stellt sicher, dass unsere Klasse das durch das Interface definierte Verhalten erbt.
Da Interfaces nur Methodendeklarationen bereitstellen, müssen Sie diese Methoden in unserer Klasse überschreiben und implementieren.
Nun werden in unserer Klasse alle Methoden angezeigt, die überschrieben werden müssen. Lassen Sie uns dies nun tun!
TaskQueueServiceImpl.java
1234567891011121314151617181920212223242526package 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 unserem Fall wurde nichts allzu Kompliziertes gemacht. Wir haben einfach die Methoden der Queue-Klasse verwendet, um unsere Methoden korrekt zu implementieren. Somit erleichtert eine Datenstruktur wie eine Queue allen Java-Programmierern das Leben.
Wir verwenden die Methode offer() zum Hinzufügen, die Methode poll() zum Entfernen und die Methode isEmpty(), um zu prüfen, ob die Queue leer ist.
Nun sind Sie an der Reihe, dieses Problem zu lösen. Sie müssen eine Service-Klasse implementieren, deren Schnittstelle wir gemeinsam erstellen werden:
Main.java
12345package codefinity.taskManager; public interface TaskProcessorService { void processTasks(); }
Wir haben ein Service-Interface mit einer Methode erstellt: processTasks(), die beim Aufruf alle Aufgaben ausführen soll, bis die Aufgabenliste leer ist. Diese Methode repräsentiert das Starten der Aufgabenbearbeitung durch einen Benutzer.
Aufgabe
Ihre Aufgabe ist es, eine Klasse TaskProcessorServiceImpl zu schreiben, die das Interface TaskProcessorService implementiert. Diese Klasse sollte eine Methode enthalten, um alle Aufgaben zu verarbeiten, das heißt, sie sollte Methoden des Dienstes TaskQueueService verwenden. Sie können Komposition nutzen, indem Sie eine Instanz dieser Klasse innerhalb der zu implementierenden Klasse erstellen, zum Beispiel:
Main.java
1234567package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.TaskQueueService; public class TaskProcessorServiceImpl { TaskQueueService taskQueueService = new TaskQueueServiceImpl(); }
Im Allgemeinen ist bereits eine vorbereitete Komposition oben für Ihre Aufgabe vorhanden. Anschließend müssen Sie lediglich eine Methode implementieren, indem Sie eine Instanz dieser Klasse verwenden.
Danach müssen Sie einen Konstruktor erstellen, der dieses Objekt der Klasse taskQueueService initialisiert.
Auf diese Weise können Sie die Methoden dieses Objekts verwenden. Es ist ebenfalls ersichtlich, dass Sie zur Aufgabenverarbeitung die Warteschlange übergeben müssen, mit der der taskProcessor arbeitet.
Der Rest der Aufgabe bleibt Ihnen überlassen. Hinweise finden Sie in der Datei README.md. Sobald Ihre Lösung fertig ist, klicken Sie auf die Schaltfläche "Run Tests", und die von mir geschriebenen Unit-Tests überprüfen Ihre Lösung.
- Zuerst sollte Komposition verwendet und eine Instanz der Klasse
TaskQueueerstellt werden. Fügen Sie dann auch deren Initialisierung im Konstruktor hinzu. - Implementieren Sie anschließend das Interface
TaskProcessorImplund überschreiben Sie dessen Methoden. - Verwenden Sie in der Implementierung des Interfaces eine while-Schleife mit der Methode
isEmpty()als Bedingung. - Verwenden Sie innerhalb der
while-Schleife die MethodetaskQueueService.getNextTask(), um anzugeben, dass die Aufgabe abgeschlossen ist. Geben Sie Informationen mitSystem.out.println()aus –"Processing Task: " + task. - Wenn die Schleife beendet ist, geben Sie
"All tasks processed."auf dem Bildschirm aus. - Führen Sie die Tests aus und überprüfen Sie die Korrektheit Ihrer Lösung.
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.");
}
}
Danke für Ihr Feedback!
Fragen Sie AI
Fragen Sie AI
Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen
Großartig!
Completion Rate verbessert auf 4
Herausforderung: Implementierung eines Taskmanager-Dienstes
Swipe um das Menü anzuzeigen
Übung
Es ist Zeit zum Üben. Die Aufgabe besteht darin, einen TaskManager-Dienst zu implementieren, der Aufgaben verwaltet.
Mit diesem Dienst kann der Benutzer Aufgaben hinzufügen, sie sich zuweisen und sie anschließend in einer festgelegten Reihenfolge erledigen.
Lassen Sie uns gemeinsam mit dieser Aufgabe beginnen; anschließend führen Sie sie eigenständig fort.
Zunächst muss das Task-Modell selbst erstellt werden. Erstellen Sie eine Task-Klasse:
Main.java
12345public class Task { private int id; private String name; private String description; }
Die Task-Klasse enthält drei Attribute: id, name und description. Jede Aufgabe muss einen Namen und eine Beschreibung besitzen, und id ist ein notwendiges Attribut für jede Datenstruktur.
Wie sonst könnten Sie auf die Elemente zugreifen?
Die Attribute sind außerdem durch den Zugriffsmodifizierer private geschützt, da andere Klassen keinen direkten Zugriff auf die Felder dieser Klasse haben sollen, außer über den Konstruktor oder Getter.
Nun implementieren wir diese Getter und den Konstruktor. Dies kann einfach durch die Kombination von Control + Return auf einem MacBook oder Alt + Ins unter Windows erledigt werden.
Nach den durchgeführten Operationen haben Sie die folgende Task-Klasse:
Task.java
12345678910111213141516171819202122232425262728293031323334package 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
Sie arbeiten mit einem stark vereinfachten Task-Board-Service. Implementieren Sie einen Service, der Aufgaben hinzufügt, sie als erledigt markiert und überprüft, ob Aufgaben in der Warteschlange vorhanden sind.
Nennen wir diese Klasse TaskQueueService.
Zunächst muss ein Interface mit diesen Aufgaben definiert werden:
TaskQueueService.java
123456789package codefinity.taskManager; public interface TaskQueueService { void addTask(Task task); Task getNextTask(); boolean isEmpty(); }
Dieses Interface definiert 3 Methoden, die von Implementierungsklassen umgesetzt werden müssen. Dazu gehören das Hinzufügen einer Aufgabe, das Wechseln zur nächsten Aufgabe (was voraussetzt, dass die vorherige Aufgabe bereits erledigt wurde), sowie eine Methode zur Überprüfung, ob Aufgaben in der Warteschlange vorhanden sind.
Sehr gut, erstellen wir nun eine Implementierungsklasse, die alle diese Methoden überschreibt und implementiert:
TaskQueueServiceImpl.java
12345678910package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.Task; import java.util.LinkedList; import java.util.Queue; public class TaskQueueServiceImpl { private Queue<Task> taskQueue = new LinkedList<>(); }
Wir erstellen ein privates Attribut, das ausschließlich innerhalb dieser Serviceklasse verwendet wird.
Es lohnt sich, einen kurzen Exkurs zu machen, um über Serviceklassen zu sprechen, die eine Schlüsselrolle in der OOP spielen.
Was sind Serviceklassen?
Serviceklassen sind dafür konzipiert, spezifische Operationen auszuführen. Sie erben von Service-Interfaces und implementieren deren Methoden. Dieser Ansatz verbessert die Wartbarkeit und Skalierbarkeit des Codes und folgt den SOLID-Prinzipien, die Sie in einem separaten Kurs kennenlernen werden.
Für den Moment ist es wichtig zu verstehen, dass Serviceklassen ausschließlich dazu dienen, Operationen an anderen Objekten auszuführen.
Beispielsweise Wenn Sie einen Taschenrechner programmieren, gibt es eine separate Klasse, die den Wert der Zahl, mit der Sie arbeiten, speichert. Die eigentlichen Operationen werden mit einer Serviceklasse durchgeführt, in der Addition, Subtraktion usw. definiert sind.
Ich hoffe, dies verdeutlicht den Zweck von Serviceklassen bei der Lösung der aktuellen Aufgabe.
Service-Implementierung
Unser nächster Schritt ist es, explizit zu zeigen, dass diese Klasse das Interface TaskQueueService implementiert.
Dazu verwenden wir das Schlüsselwort implements gefolgt vom Namen des Interfaces. Dies stellt sicher, dass unsere Klasse das durch das Interface definierte Verhalten erbt.
Da Interfaces nur Methodendeklarationen bereitstellen, müssen Sie diese Methoden in unserer Klasse überschreiben und implementieren.
Nun werden in unserer Klasse alle Methoden angezeigt, die überschrieben werden müssen. Lassen Sie uns dies nun tun!
TaskQueueServiceImpl.java
1234567891011121314151617181920212223242526package 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 unserem Fall wurde nichts allzu Kompliziertes gemacht. Wir haben einfach die Methoden der Queue-Klasse verwendet, um unsere Methoden korrekt zu implementieren. Somit erleichtert eine Datenstruktur wie eine Queue allen Java-Programmierern das Leben.
Wir verwenden die Methode offer() zum Hinzufügen, die Methode poll() zum Entfernen und die Methode isEmpty(), um zu prüfen, ob die Queue leer ist.
Nun sind Sie an der Reihe, dieses Problem zu lösen. Sie müssen eine Service-Klasse implementieren, deren Schnittstelle wir gemeinsam erstellen werden:
Main.java
12345package codefinity.taskManager; public interface TaskProcessorService { void processTasks(); }
Wir haben ein Service-Interface mit einer Methode erstellt: processTasks(), die beim Aufruf alle Aufgaben ausführen soll, bis die Aufgabenliste leer ist. Diese Methode repräsentiert das Starten der Aufgabenbearbeitung durch einen Benutzer.
Aufgabe
Ihre Aufgabe ist es, eine Klasse TaskProcessorServiceImpl zu schreiben, die das Interface TaskProcessorService implementiert. Diese Klasse sollte eine Methode enthalten, um alle Aufgaben zu verarbeiten, das heißt, sie sollte Methoden des Dienstes TaskQueueService verwenden. Sie können Komposition nutzen, indem Sie eine Instanz dieser Klasse innerhalb der zu implementierenden Klasse erstellen, zum Beispiel:
Main.java
1234567package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.TaskQueueService; public class TaskProcessorServiceImpl { TaskQueueService taskQueueService = new TaskQueueServiceImpl(); }
Im Allgemeinen ist bereits eine vorbereitete Komposition oben für Ihre Aufgabe vorhanden. Anschließend müssen Sie lediglich eine Methode implementieren, indem Sie eine Instanz dieser Klasse verwenden.
Danach müssen Sie einen Konstruktor erstellen, der dieses Objekt der Klasse taskQueueService initialisiert.
Auf diese Weise können Sie die Methoden dieses Objekts verwenden. Es ist ebenfalls ersichtlich, dass Sie zur Aufgabenverarbeitung die Warteschlange übergeben müssen, mit der der taskProcessor arbeitet.
Der Rest der Aufgabe bleibt Ihnen überlassen. Hinweise finden Sie in der Datei README.md. Sobald Ihre Lösung fertig ist, klicken Sie auf die Schaltfläche "Run Tests", und die von mir geschriebenen Unit-Tests überprüfen Ihre Lösung.
- Zuerst sollte Komposition verwendet und eine Instanz der Klasse
TaskQueueerstellt werden. Fügen Sie dann auch deren Initialisierung im Konstruktor hinzu. - Implementieren Sie anschließend das Interface
TaskProcessorImplund überschreiben Sie dessen Methoden. - Verwenden Sie in der Implementierung des Interfaces eine while-Schleife mit der Methode
isEmpty()als Bedingung. - Verwenden Sie innerhalb der
while-Schleife die MethodetaskQueueService.getNextTask(), um anzugeben, dass die Aufgabe abgeschlossen ist. Geben Sie Informationen mitSystem.out.println()aus –"Processing Task: " + task. - Wenn die Schleife beendet ist, geben Sie
"All tasks processed."auf dem Bildschirm aus. - Führen Sie die Tests aus und überprüfen Sie die Korrektheit Ihrer Lösung.
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.");
}
}
Danke für Ihr Feedback!