Desafio: Implementando um Serviço de TaskManager
Prática
É hora de praticar. Você tem a tarefa de implementar um serviço TaskManager que irá acompanhar suas tarefas.
Com este serviço, o usuário pode adicionar tarefas, atribuí-las a si mesmo e, em seguida, concluí-las em ordem sequencial.
Vamos começar a trabalhar nesta tarefa juntos e, depois, você continuará sozinho.
Mas antes, é necessário criar o próprio modelo de tarefa. Vamos criar uma classe Task:
Main.java
12345public class Task { private int id; private String name; private String description; }
A classe Task contém três atributos: id, name e description. Cada tarefa deve possuir um nome e descrição, e id é um atributo necessário para qualquer estrutura de dados.
Como seria possível acessar os elementos de outra forma?
Os atributos também são protegidos pelo modificador de acesso private, pois não se deseja que outras classes tenham acesso direto aos campos desta classe, exceto por meio do construtor ou dos getters.
Agora, implemente esses getters e o construtor. Isso pode ser feito facilmente utilizando a combinação de Control + Return em um MacBook ou Alt + Ins em um Windows.
Após as operações realizadas, você possui a seguinte classe Task:
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 + '\'' + '}'; } }
Serviços
Você terá um serviço de quadro de tarefas bastante simplificado, então vamos implementar um serviço que irá adicionar tarefas, marcá-las como concluídas e verificar se há tarefas na fila.
Vamos chamar essa classe de TaskQueueService.
Para começar, precisamos definir uma interface com essas tarefas:
TaskQueueService.java
123456789package codefinity.taskManager; public interface TaskQueueService { void addTask(Task task); Task getNextTask(); boolean isEmpty(); }
Esta interface define 3 métodos que as classes de implementação devem implementar. Esses métodos incluem adicionar uma tarefa, avançar para a próxima tarefa (implicando que o usuário já concluiu a tarefa anterior) e um método para verificar se há tarefas na fila.
Ótimo, agora vamos criar uma classe de implementação que irá sobrescrever e implementar todos esses métodos:
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<>(); }
Criamos um atributo privado que será utilizado apenas dentro desta classe de serviço.
Vale a pena fazer uma pequena digressão para falar sobre classes de serviço, que desempenham um papel fundamental na POO.
O que são Classes de Serviço?
Classes de serviço são projetadas para realizar operações específicas. Elas herdam de interfaces de serviço e implementam seus métodos. Essa abordagem melhora a manutenibilidade e escalabilidade do código, além de seguir os princípios SOLID, que serão explorados em um curso separado.
Por enquanto, é fundamental entender que classes de serviço existem unicamente para realizar operações em outros objetos.
Por exemplo, Se você estiver desenvolvendo uma calculadora, terá uma classe separada que armazenará o valor do número sobre o qual você opera. As operações propriamente ditas serão realizadas por meio de uma classe de serviço, onde são definidas a soma, subtração, entre outras.
Espero que isso esclareça o propósito das classes de serviço na resolução desta tarefa.
Implementação do Serviço
Nosso próximo passo é mostrar explicitamente que esta classe implementa a interface TaskQueueService.
Para isso, utilizamos a palavra-chave implements seguida do nome da interface. Isso garante que nossa classe herde o comportamento definido pela interface.
Como as interfaces fornecem apenas declarações de métodos, é necessário sobrescrever e implementar esses métodos em nossa classe.
Agora, em nossa classe, todos os métodos que precisam ser sobrescritos estão exibidos. Vamos prosseguir e realizá-los!
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(); } }
No nosso caso, nada muito complicado foi feito. Simplesmente utilizamos os métodos da classe Queue para implementar nossos métodos corretamente. Assim, uma estrutura de dados como uma fila facilita a vida de todos os programadores Java.
Utilizamos o método offer() para adicionar, o método poll() para remover e o método isEmpty() para verificar se a fila está vazia.
Agora é sua vez de participar na resolução deste problema. Você precisará implementar uma classe de serviço, cuja interface criaremos juntos:
Main.java
12345package codefinity.taskManager; public interface TaskProcessorService { void processTasks(); }
Criamos uma interface de serviço com um método: processTasks(), que, quando chamado, deve iniciar a execução de todas as tarefas até que a lista de tarefas esteja vazia. Este método representa um usuário iniciando a execução das tarefas.
Tarefa
O objetivo é escrever uma classe TaskProcessorServiceImpl que deve implementar a interface TaskProcessorService. Esta classe deve possuir um método para processar todas as tarefas, ou seja, deve utilizar métodos do serviço TaskQueueService. É possível utilizar composição criando uma instância desta classe dentro da classe que precisa ser implementada, por exemplo:
Main.java
1234567package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.TaskQueueService; public class TaskProcessorServiceImpl { TaskQueueService taskQueueService = new TaskQueueServiceImpl(); }
De modo geral, já existe uma composição preparada no topo para sua tarefa. Em seguida, basta implementar um método utilizando uma instância desta classe.
Depois disso, é necessário criar um construtor que irá inicializar este objeto da classe taskQueueService.
Dessa forma, será possível utilizar os métodos deste objeto. Também é evidente que, para o processamento das tarefas, é preciso passar a fila com a qual o taskProcessor irá trabalhar.
O restante da tarefa fica a seu critério. Dicas serão fornecidas no arquivo README.md. Assim que sua solução estiver pronta, clique no botão "Run Tests", e os testes unitários que escrevi irão verificar sua solução.
- Primeiro, utilize composição e crie uma instância da classe
TaskQueue. Em seguida, adicione também sua inicialização no construtor. - Depois, implemente a interface
TaskProcessorImple sobrescreva seus métodos. - Na implementação da interface, utilize um laço while com o método
isEmpty()como condição. - Dentro do laço
while, utilize o métodotaskQueueService.getNextTask(), indicando que a tarefa foi concluída. Exiba informações na tela utilizandoSystem.out.println()-"Processing Task: " + task. - Quando o laço finalizar, exiba
"All tasks processed."na tela. - Execute os testes e verifique a correção da sua solução.
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.");
}
}
Obrigado pelo seu feedback!
Pergunte à IA
Pergunte à IA
Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo
Incrível!
Completion taxa melhorada para 4
Desafio: Implementando um Serviço de TaskManager
Deslize para mostrar o menu
Prática
É hora de praticar. Você tem a tarefa de implementar um serviço TaskManager que irá acompanhar suas tarefas.
Com este serviço, o usuário pode adicionar tarefas, atribuí-las a si mesmo e, em seguida, concluí-las em ordem sequencial.
Vamos começar a trabalhar nesta tarefa juntos e, depois, você continuará sozinho.
Mas antes, é necessário criar o próprio modelo de tarefa. Vamos criar uma classe Task:
Main.java
12345public class Task { private int id; private String name; private String description; }
A classe Task contém três atributos: id, name e description. Cada tarefa deve possuir um nome e descrição, e id é um atributo necessário para qualquer estrutura de dados.
Como seria possível acessar os elementos de outra forma?
Os atributos também são protegidos pelo modificador de acesso private, pois não se deseja que outras classes tenham acesso direto aos campos desta classe, exceto por meio do construtor ou dos getters.
Agora, implemente esses getters e o construtor. Isso pode ser feito facilmente utilizando a combinação de Control + Return em um MacBook ou Alt + Ins em um Windows.
Após as operações realizadas, você possui a seguinte classe Task:
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 + '\'' + '}'; } }
Serviços
Você terá um serviço de quadro de tarefas bastante simplificado, então vamos implementar um serviço que irá adicionar tarefas, marcá-las como concluídas e verificar se há tarefas na fila.
Vamos chamar essa classe de TaskQueueService.
Para começar, precisamos definir uma interface com essas tarefas:
TaskQueueService.java
123456789package codefinity.taskManager; public interface TaskQueueService { void addTask(Task task); Task getNextTask(); boolean isEmpty(); }
Esta interface define 3 métodos que as classes de implementação devem implementar. Esses métodos incluem adicionar uma tarefa, avançar para a próxima tarefa (implicando que o usuário já concluiu a tarefa anterior) e um método para verificar se há tarefas na fila.
Ótimo, agora vamos criar uma classe de implementação que irá sobrescrever e implementar todos esses métodos:
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<>(); }
Criamos um atributo privado que será utilizado apenas dentro desta classe de serviço.
Vale a pena fazer uma pequena digressão para falar sobre classes de serviço, que desempenham um papel fundamental na POO.
O que são Classes de Serviço?
Classes de serviço são projetadas para realizar operações específicas. Elas herdam de interfaces de serviço e implementam seus métodos. Essa abordagem melhora a manutenibilidade e escalabilidade do código, além de seguir os princípios SOLID, que serão explorados em um curso separado.
Por enquanto, é fundamental entender que classes de serviço existem unicamente para realizar operações em outros objetos.
Por exemplo, Se você estiver desenvolvendo uma calculadora, terá uma classe separada que armazenará o valor do número sobre o qual você opera. As operações propriamente ditas serão realizadas por meio de uma classe de serviço, onde são definidas a soma, subtração, entre outras.
Espero que isso esclareça o propósito das classes de serviço na resolução desta tarefa.
Implementação do Serviço
Nosso próximo passo é mostrar explicitamente que esta classe implementa a interface TaskQueueService.
Para isso, utilizamos a palavra-chave implements seguida do nome da interface. Isso garante que nossa classe herde o comportamento definido pela interface.
Como as interfaces fornecem apenas declarações de métodos, é necessário sobrescrever e implementar esses métodos em nossa classe.
Agora, em nossa classe, todos os métodos que precisam ser sobrescritos estão exibidos. Vamos prosseguir e realizá-los!
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(); } }
No nosso caso, nada muito complicado foi feito. Simplesmente utilizamos os métodos da classe Queue para implementar nossos métodos corretamente. Assim, uma estrutura de dados como uma fila facilita a vida de todos os programadores Java.
Utilizamos o método offer() para adicionar, o método poll() para remover e o método isEmpty() para verificar se a fila está vazia.
Agora é sua vez de participar na resolução deste problema. Você precisará implementar uma classe de serviço, cuja interface criaremos juntos:
Main.java
12345package codefinity.taskManager; public interface TaskProcessorService { void processTasks(); }
Criamos uma interface de serviço com um método: processTasks(), que, quando chamado, deve iniciar a execução de todas as tarefas até que a lista de tarefas esteja vazia. Este método representa um usuário iniciando a execução das tarefas.
Tarefa
O objetivo é escrever uma classe TaskProcessorServiceImpl que deve implementar a interface TaskProcessorService. Esta classe deve possuir um método para processar todas as tarefas, ou seja, deve utilizar métodos do serviço TaskQueueService. É possível utilizar composição criando uma instância desta classe dentro da classe que precisa ser implementada, por exemplo:
Main.java
1234567package codefinity.taskManager.taskManagerImpl; import codefinity.taskManager.TaskQueueService; public class TaskProcessorServiceImpl { TaskQueueService taskQueueService = new TaskQueueServiceImpl(); }
De modo geral, já existe uma composição preparada no topo para sua tarefa. Em seguida, basta implementar um método utilizando uma instância desta classe.
Depois disso, é necessário criar um construtor que irá inicializar este objeto da classe taskQueueService.
Dessa forma, será possível utilizar os métodos deste objeto. Também é evidente que, para o processamento das tarefas, é preciso passar a fila com a qual o taskProcessor irá trabalhar.
O restante da tarefa fica a seu critério. Dicas serão fornecidas no arquivo README.md. Assim que sua solução estiver pronta, clique no botão "Run Tests", e os testes unitários que escrevi irão verificar sua solução.
- Primeiro, utilize composição e crie uma instância da classe
TaskQueue. Em seguida, adicione também sua inicialização no construtor. - Depois, implemente a interface
TaskProcessorImple sobrescreva seus métodos. - Na implementação da interface, utilize um laço while com o método
isEmpty()como condição. - Dentro do laço
while, utilize o métodotaskQueueService.getNextTask(), indicando que a tarefa foi concluída. Exiba informações na tela utilizandoSystem.out.println()-"Processing Task: " + task. - Quando o laço finalizar, exiba
"All tasks processed."na tela. - Execute os testes e verifique a correção da sua solução.
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.");
}
}
Obrigado pelo seu feedback!