Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Haaste: Tehtävienhallintapalvelun Toteuttaminen | Edistyneet Tietorakenteet Javassa
Java-tietorakenteet

bookHaaste: Tehtävienhallintapalvelun Toteuttaminen

Harjoittelu

On aika harjoitella. Sinulla on tehtävänä kirjoittaa TaskManager-palvelu, joka seuraa tehtäviäsi.

Tämän palvelun avulla käyttäjä voi lisätä tehtäviä, ottaa niitä itselleen ja suorittaa ne järjestyksessä.

Aloitetaan tämän tehtävän ratkaiseminen yhdessä, ja jatkat sen jälkeen itsenäisesti.

Mutta ensin sinun täytyy luoda itse tehtävämalli. Luodaan Task-luokka:

Main.java

Main.java

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

Task-luokalla on kolme attribuuttia: id, name ja description. Jokaisella tehtävällä tulee olla nimi ja kuvaus, ja id on välttämätön attribuutti kaikissa tietorakenteissa.

Miten muuten pääsisit käsiksi alkioihin? Attribuutit on myös suojattu private-näkyvyysmuuttujalla, koska et halua muiden luokkien pääsevän suoraan käsiksi tämän luokan kenttiin, paitsi konstruktorin tai getterien kautta.

Seuraavaksi toteutetaan nämä getterit ja konstruktori. Tämä onnistuu helposti käyttämällä yhdistelmää Control + Return MacBookilla tai Alt + Ins Windowsilla.

Suoritettujen operaatioiden jälkeen sinulla on seuraavanlainen Task-luokka:

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

Palvelut

Toteutetaan hyvin yksinkertaistettu tehtävätaulupalvelu, joka mahdollistaa tehtävien lisäämisen, merkitsemisen suoritetuiksi sekä tarkistamisen, onko jonossa tehtäviä.

Nimetään tämä luokka TaskQueueService. Aluksi meidän tulee määritellä rajapinta, jossa nämä tehtävät määritellään:

TaskQueueService.java

TaskQueueService.java

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

Tämä rajapinta määrittelee kolme metodia, jotka toteuttavien luokkien täytyy toteuttaa. Näihin metodeihin kuuluu tehtävän lisääminen, siirtyminen seuraavaan tehtävään (olettaen, että käyttäjä on jo suorittanut edellisen tehtävän), sekä metodi, jolla tarkistetaan onko jonossa tehtäviä.

Erinomaista, luodaan nyt toteutusluokka, joka ylikirjoittaa ja toteuttaa kaikki nämä metodit:

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

Luomme yksityisen attribuutin, jota käytetään vain tässä palveluluokassa.

On syytä tehdä lyhyt sivuhuomautus palveluluokista, jotka ovat keskeisessä asemassa olio-ohjelmoinnissa.

Mitä ovat palveluluokat?

Palveluluokat on suunniteltu suorittamaan tiettyjä operaatioita. Ne perivät palvelurajapinnoista ja toteuttavat niiden metodit. Tämä lähestymistapa parantaa koodin ylläpidettävyyttä ja laajennettavuutta sekä noudattaa SOLID-periaatteita, joihin perehdyt erillisellä kurssilla.

Tällä hetkellä on tärkeää ymmärtää, että palveluluokat on tarkoitettu ainoastaan suorittamaan operaatioita muille olioille.

Esimerkiksi, Jos kirjoitat laskimen, sinulla on erillinen luokka, joka tallentaa käsiteltävän luvun arvon. Varsinaiset operaatiot suoritetaan palveluluokan avulla, jossa määritellään yhteen-, vähennyslasku ja muut toiminnot.

Toivottavasti tämä selventää palveluluokkien tarkoitusta tämän tehtävän ratkaisussa.

Palvelun toteutus

Seuraava vaihe on osoittaa selkeästi, että tämä luokka toteuttaa TaskQueueService-rajapinnan.

Tämä tehdään käyttämällä implements-avainsanaa ja lisäämällä rajapinnan nimi. Näin varmistetaan, että luokka perii rajapinnan määrittelemän toiminnallisuuden.

Koska rajapinnat sisältävät vain metodien määrittelyt, nämä metodit täytyy ylikirjoittaa ja toteuttaa omassa luokassa.

Nyt luokassamme on kaikki metodit, jotka täytyy ylikirjoittaa, esitetty. Jatketaan ja tehdään se!

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

Tässä tapauksessa mitään erityisen monimutkaista ei tehty. Käytimme yksinkertaisesti Queue-luokan metodeja toteuttaaksemme omat metodimme oikein. Tämän ansiosta jonorakenteen kaltainen tietorakenne helpottaa kaikkien Java-ohjelmoijien elämää.

Käytämme offer()-metodia lisäämiseen, poll()-metodia poistamiseen ja isEmpty()-metodia tarkistaaksemme, onko jono tyhjä.

Nyt on sinun vuorosi osallistua tämän ongelman ratkaisuun. Sinun tulee toteuttaa palveluluokka, jonka rajapinnan luomme yhdessä:

Main.java

Main.java

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

Olemme luoneet palvelurajapinnan, jossa on yksi metodi: processTasks(). Kun tätä kutsutaan, sen tulee aloittaa kaikkien tehtävien suorittaminen, kunnes tehtävälista on tyhjä. Tämä metodi edustaa käyttäjän aloittamaa tehtävien suorittamista.

Tehtävä

Kirjoita luokka TaskProcessorServiceImpl, jonka tulee toteuttaa TaskProcessorService-rajapinta. Tämän luokan tulee sisältää metodi kaikkien tehtävien käsittelemiseksi, eli sen tulee käyttää TaskQueueService-palvelun metodeja. Voit käyttää koostamista luomalla tämän luokan instanssin toteutettavaan luokkaan, esimerkiksi:

Main.java

Main.java

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

Yleisesti ottaen tehtävääsi varten on jo valmiiksi valmisteltu koostelu ylhäällä. Seuraavaksi sinun tarvitsee vain toteuttaa yksi metodi käyttämällä tämän luokan instanssia.

Tämän jälkeen sinun tulee luoda konstruktori, joka alustaa tämän taskQueueService-luokan olion.

Näin voit käyttää tämän olion metodeja. On myös selvää, että tehtävien käsittelyä varten sinun täytyy välittää jono, jonka kanssa taskProcessor työskentelee.

Loput tehtävästä jää sinulle. Vihjeitä löytyy README.md-tiedostosta. Kun ratkaisusi on valmis, napsauta "Run Tests" -painiketta, jolloin kirjoittamani yksikkötestit tarkistavat ratkaisusi.

  1. Käytä ensin koostetta ja luo TaskQueue-luokan instanssi. Lisää myös sen alustus konstruktoriin.
  2. Toteuta seuraavaksi TaskProcessorImpl-rajapinta ja ylikirjoita sen metodit.
  3. Rajapinnan toteutuksessa käytä while-silmukkaa, jonka ehtona on isEmpty()-metodi.
  4. while-silmukan sisällä käytä taskQueueService.getNextTask()-metodia osoittaen, että tehtävä on suoritettu. Tulosta tietoa näytölle käyttäen System.out.println() - "Processing Task: " + task.
  5. Kun silmukka on suorittanut työnsä, tulosta "All tasks processed." näytölle.
  6. Suorita testit ja tarkista ratkaisusi oikeellisuus.
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.");
    }
}
Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 2. Luku 3

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme

bookHaaste: Tehtävienhallintapalvelun Toteuttaminen

Pyyhkäise näyttääksesi valikon

Harjoittelu

On aika harjoitella. Sinulla on tehtävänä kirjoittaa TaskManager-palvelu, joka seuraa tehtäviäsi.

Tämän palvelun avulla käyttäjä voi lisätä tehtäviä, ottaa niitä itselleen ja suorittaa ne järjestyksessä.

Aloitetaan tämän tehtävän ratkaiseminen yhdessä, ja jatkat sen jälkeen itsenäisesti.

Mutta ensin sinun täytyy luoda itse tehtävämalli. Luodaan Task-luokka:

Main.java

Main.java

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

Task-luokalla on kolme attribuuttia: id, name ja description. Jokaisella tehtävällä tulee olla nimi ja kuvaus, ja id on välttämätön attribuutti kaikissa tietorakenteissa.

Miten muuten pääsisit käsiksi alkioihin? Attribuutit on myös suojattu private-näkyvyysmuuttujalla, koska et halua muiden luokkien pääsevän suoraan käsiksi tämän luokan kenttiin, paitsi konstruktorin tai getterien kautta.

Seuraavaksi toteutetaan nämä getterit ja konstruktori. Tämä onnistuu helposti käyttämällä yhdistelmää Control + Return MacBookilla tai Alt + Ins Windowsilla.

Suoritettujen operaatioiden jälkeen sinulla on seuraavanlainen Task-luokka:

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

Palvelut

Toteutetaan hyvin yksinkertaistettu tehtävätaulupalvelu, joka mahdollistaa tehtävien lisäämisen, merkitsemisen suoritetuiksi sekä tarkistamisen, onko jonossa tehtäviä.

Nimetään tämä luokka TaskQueueService. Aluksi meidän tulee määritellä rajapinta, jossa nämä tehtävät määritellään:

TaskQueueService.java

TaskQueueService.java

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

Tämä rajapinta määrittelee kolme metodia, jotka toteuttavien luokkien täytyy toteuttaa. Näihin metodeihin kuuluu tehtävän lisääminen, siirtyminen seuraavaan tehtävään (olettaen, että käyttäjä on jo suorittanut edellisen tehtävän), sekä metodi, jolla tarkistetaan onko jonossa tehtäviä.

Erinomaista, luodaan nyt toteutusluokka, joka ylikirjoittaa ja toteuttaa kaikki nämä metodit:

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

Luomme yksityisen attribuutin, jota käytetään vain tässä palveluluokassa.

On syytä tehdä lyhyt sivuhuomautus palveluluokista, jotka ovat keskeisessä asemassa olio-ohjelmoinnissa.

Mitä ovat palveluluokat?

Palveluluokat on suunniteltu suorittamaan tiettyjä operaatioita. Ne perivät palvelurajapinnoista ja toteuttavat niiden metodit. Tämä lähestymistapa parantaa koodin ylläpidettävyyttä ja laajennettavuutta sekä noudattaa SOLID-periaatteita, joihin perehdyt erillisellä kurssilla.

Tällä hetkellä on tärkeää ymmärtää, että palveluluokat on tarkoitettu ainoastaan suorittamaan operaatioita muille olioille.

Esimerkiksi, Jos kirjoitat laskimen, sinulla on erillinen luokka, joka tallentaa käsiteltävän luvun arvon. Varsinaiset operaatiot suoritetaan palveluluokan avulla, jossa määritellään yhteen-, vähennyslasku ja muut toiminnot.

Toivottavasti tämä selventää palveluluokkien tarkoitusta tämän tehtävän ratkaisussa.

Palvelun toteutus

Seuraava vaihe on osoittaa selkeästi, että tämä luokka toteuttaa TaskQueueService-rajapinnan.

Tämä tehdään käyttämällä implements-avainsanaa ja lisäämällä rajapinnan nimi. Näin varmistetaan, että luokka perii rajapinnan määrittelemän toiminnallisuuden.

Koska rajapinnat sisältävät vain metodien määrittelyt, nämä metodit täytyy ylikirjoittaa ja toteuttaa omassa luokassa.

Nyt luokassamme on kaikki metodit, jotka täytyy ylikirjoittaa, esitetty. Jatketaan ja tehdään se!

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

Tässä tapauksessa mitään erityisen monimutkaista ei tehty. Käytimme yksinkertaisesti Queue-luokan metodeja toteuttaaksemme omat metodimme oikein. Tämän ansiosta jonorakenteen kaltainen tietorakenne helpottaa kaikkien Java-ohjelmoijien elämää.

Käytämme offer()-metodia lisäämiseen, poll()-metodia poistamiseen ja isEmpty()-metodia tarkistaaksemme, onko jono tyhjä.

Nyt on sinun vuorosi osallistua tämän ongelman ratkaisuun. Sinun tulee toteuttaa palveluluokka, jonka rajapinnan luomme yhdessä:

Main.java

Main.java

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

Olemme luoneet palvelurajapinnan, jossa on yksi metodi: processTasks(). Kun tätä kutsutaan, sen tulee aloittaa kaikkien tehtävien suorittaminen, kunnes tehtävälista on tyhjä. Tämä metodi edustaa käyttäjän aloittamaa tehtävien suorittamista.

Tehtävä

Kirjoita luokka TaskProcessorServiceImpl, jonka tulee toteuttaa TaskProcessorService-rajapinta. Tämän luokan tulee sisältää metodi kaikkien tehtävien käsittelemiseksi, eli sen tulee käyttää TaskQueueService-palvelun metodeja. Voit käyttää koostamista luomalla tämän luokan instanssin toteutettavaan luokkaan, esimerkiksi:

Main.java

Main.java

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

Yleisesti ottaen tehtävääsi varten on jo valmiiksi valmisteltu koostelu ylhäällä. Seuraavaksi sinun tarvitsee vain toteuttaa yksi metodi käyttämällä tämän luokan instanssia.

Tämän jälkeen sinun tulee luoda konstruktori, joka alustaa tämän taskQueueService-luokan olion.

Näin voit käyttää tämän olion metodeja. On myös selvää, että tehtävien käsittelyä varten sinun täytyy välittää jono, jonka kanssa taskProcessor työskentelee.

Loput tehtävästä jää sinulle. Vihjeitä löytyy README.md-tiedostosta. Kun ratkaisusi on valmis, napsauta "Run Tests" -painiketta, jolloin kirjoittamani yksikkötestit tarkistavat ratkaisusi.

  1. Käytä ensin koostetta ja luo TaskQueue-luokan instanssi. Lisää myös sen alustus konstruktoriin.
  2. Toteuta seuraavaksi TaskProcessorImpl-rajapinta ja ylikirjoita sen metodit.
  3. Rajapinnan toteutuksessa käytä while-silmukkaa, jonka ehtona on isEmpty()-metodi.
  4. while-silmukan sisällä käytä taskQueueService.getNextTask()-metodia osoittaen, että tehtävä on suoritettu. Tulosta tietoa näytölle käyttäen System.out.println() - "Processing Task: " + task.
  5. Kun silmukka on suorittanut työnsä, tulosta "All tasks processed." näytölle.
  6. Suorita testit ja tarkista ratkaisusi oikeellisuus.
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.");
    }
}
Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 2. Luku 3
some-alt