📚 POO & APOO — Notas de Aula

Prog. Orientada a Objetos  |  Analise e Projeto OO

POO — Módulo 1 · Fundamentos de Orientação a Objetos
Unidade 1 · Introdução ao Paradigma OO

A Programação Orientada a Objetos (POO) organiza o código em torno de objetos que combinam dados (atributos) e comportamentos (métodos). É o paradigma dominante no desenvolvimento de software moderno.

Paradigma Procedural
Foco em funções e procedimentos. Dados e funções separados. Difícil de escalar e manter. Ex: C, Pascal.
Paradigma OO
Foco em objetos. Dados + comportamento juntos. Modela o mundo real. Reutilizável. Ex: Java, Python, C++.
Os 4 Pilares da POO
PilarO que éExemplo
EncapsulamentoEsconder dados internos, expor só o necessárioAtributos private + getters/setters
HerançaUma classe reutiliza atributos/métodos de outraCachorro extends Animal
PolimorfismoO mesmo método se comporta diferente por tipoanimal.falar() → "Au" ou "Miau"
AbstraçãoModelar só o que é relevante ao problemaClasse Conta sem detalhe bancário interno
Unidade 2 · Introdução ao Java

Java é fortemente tipada, compilada e orientada a objetos. O código é compilado para bytecode que roda na JVM (Java Virtual Machine) — "escreva uma vez, rode em qualquer lugar".

// Tipos primitivos principais int idade = 20; double salario = 3500.50; boolean ativo = true; char letra = 'A'; String nome = "Ana"; // String é objeto, não primitivo // Operadores int soma = 10 + 5; // 15 int resto = 10 % 3; // 1 (módulo) boolean ok = (5 > 3); // true
⚠ Importante
Java é case-sensitive: "nome" e "Nome" são variáveis diferentes. Todo programa Java precisa de um método public static void main(String[] args) como ponto de entrada.
Unidade 3 · Classes e Objetos

A classe é o molde/template. O objeto é a instância concreta criada a partir da classe com a palavra-chave new.

// Definindo a classe public class Carro { String marca; // atributo int ano; // Construtor public Carro(String marca, int ano) { this.marca = marca; this.ano = ano; } // Método public void buzinar() { System.out.println(marca + ": Biiiip!"); } } // Criando objetos (instâncias) Carro c1 = new Carro("Toyota", 2022); Carro c2 = new Carro("Honda", 2023); c1.buzinar(); // Toyota: Biiiip!
⚠ Importante
this referencia o próprio objeto. Usado para distinguir atributos de parâmetros de mesmo nome. new aloca memória e chama o construtor.
Unidade 4 · Programando em Java — Controle de Fluxo
// if-else if (idade >= 18) { System.out.println("Maior de idade"); } else { System.out.println("Menor de idade"); } // for for (int i = 0; i < 5; i++) { System.out.println(i); } // while while (saldo > 0) { saldo -= 100; } // switch switch (dia) { case 1: System.out.println("Seg"); break; case 2: System.out.println("Ter"); break; default: System.out.println("Outro"); }

Exercícios Resolvidos
Exercício 1: Qual a diferença entre classe e objeto?
→ Classe é o molde. Objeto é a instância concreta.
Ex: Carro é a classe (define marca, ano, buzinar). Toyota 2022 é um objeto específico dessa classe. Podem existir vários objetos da mesma classe.
Exercício 2: O que faz a palavra-chave this em Java?
→ Referencia o objeto atual — distingue atributos de parâmetros com mesmo nome.
Em public Carro(String marca) { this.marca = marca; } — this.marca é o atributo, marca é o parâmetro.
POO — Módulo 2 · Aprofundando na Orientação a Objetos
Unidade 1 · Vetores (Arrays)

Um array é uma coleção de elementos do mesmo tipo com tamanho fixo. Índice começa em 0.

// Declarar e inicializar int[] notas = new int[5]; // array de 5 inteiros (default 0) String[] nomes = {"Ana","Bia","Carlos"}; // inicialização direta // Acessar e modificar notas[0] = 8; notas[1] = 9; System.out.println(notas.length); // 5 (tamanho) // Percorrer com for-each for (String n : nomes) { System.out.println(n); } // Array 2D (matriz) int[][] matriz = new int[3][3]; matriz[0][0] = 1; matriz[1][1] = 5;
⚠ Importante
Array em Java tem tamanho fixo — não pode crescer após criado. Para coleções dinâmicas, use ArrayList. Acessar índice fora do limite lança ArrayIndexOutOfBoundsException.
Unidade 2 · Métodos, Classes e Objetos — Visão Aprofundada
public class ContaBancaria { private double saldo; // encapsulado private static int totalContas; // compartilhado por todas as instâncias // Construtor public ContaBancaria(double saldoInicial) { this.saldo = saldoInicial; totalContas++; } // Método de instância public void depositar(double valor) { if (valor > 0) saldo += valor; } // Método estático public static int getTotalContas() { return totalContas; } // Sobrecarga de método (overloading) public void sacar(double valor) { saldo -= valor; } public void sacar(double valor, String motivo) { saldo -= valor; System.out.println("Saque: " + motivo); } }
ModificadorAcesso
publicQualquer classe em qualquer pacote
protectedMesma classe, mesmo pacote ou subclasses
default (sem mod.)Só mesmo pacote
privateSó a própria classe
⚠ static vs instância
static: pertence à classe — compartilhado por todos os objetos. Instância: cada objeto tem o seu. Static é acessado via NomeClasse.metodo(), não precisa de objeto.
Unidade 3 · Coleta de Lixo e Pacotes

O Garbage Collector (GC) da JVM libera automaticamente memória de objetos sem referências. Em Java, não existe delete manual como em C++.

// Pacotes organizam classes package br.edu.ufms.poo; // declara o pacote import java.util.ArrayList; // importa classe de outro pacote import java.util.*; // importa tudo do pacote java.util // Objeto sem referência → elegível para GC Carro c = new Carro("Toyota", 2022); c = null; // GC pode coletar o objeto anterior

Exercícios Resolvidos
Exercício 3: Qual a diferença entre método static e método de instância?
→ Static pertence à classe (acessado sem criar objeto). Instância pertence ao objeto (precisa de new).
ContaBancaria.getTotalContas() — static, não precisa de objeto. minhaConta.depositar(100) — instância, precisa do objeto minhaConta.
Exercício 4: O que é sobrecarga (overloading) de método?
→ Mesmo nome de método com parâmetros diferentes (tipo ou quantidade).
sacar(100.0) e sacar(100.0, "Aluguel") são sobrecargas — mesmo nome, assinaturas diferentes. O Java escolhe qual chamar pelo tipo/quantidade dos argumentos.
POO — Módulo 3 · Pilares da POO
Unidade 1 · Herança e Polimorfismo

Herança: uma classe filha (subclasse) herda atributos e métodos da classe pai (superclasse). Usa extends. Evita duplicação de código.

// Superclasse public class Animal { protected String nome; public Animal(String nome) { this.nome = nome; } public void falar() { System.out.println(nome + " faz algum som"); } } // Subclasse — herda de Animal public class Cachorro extends Animal { public Cachorro(String nome) { super(nome); // chama construtor do pai } @Override // sobrescreve o método do pai public void falar() { System.out.println(nome + ": Au Au!"); } } public class Gato extends Animal { public Gato(String nome) { super(nome); } @Override public void falar() { System.out.println(nome + ": Miau!"); } } // Polimorfismo em ação Animal[] animais = { new Cachorro("Rex"), new Gato("Mimi") }; for (Animal a : animais) { a.falar(); // cada um chama seu próprio falar() }
⚠ Importante
@Override é anotação que indica sobrescrita — o compilador verifica se o método realmente existe no pai. super acessa membros da superclasse. Java só permite herança simples (uma única superclasse).
Unidade 2 · Encapsulamento e Modificadores de Acesso
public class Pessoa { private String nome; // só acessível dentro desta classe private int idade; // Getter — leitura controlada public String getNome() { return nome; } // Setter — escrita com validação public void setIdade(int idade) { if (idade >= 0 && idade <= 150) { this.idade = idade; } } }
⚠ Encapsulamento
Atributos private + acesso via getters/setters. O setter pode validar antes de aceitar o valor — protege o estado interno do objeto de valores inválidos.
Unidade 3 · Interfaces e Abstração
// Classe abstrata — não pode ser instanciada diretamente public abstract class Forma { public abstract double calcularArea(); // sem implementação public void exibir() { // pode ter implementação System.out.println("Área: " + calcularArea()); } } // Interface — contrato puro public interface Desenhavel { void desenhar(); // implicitamente public abstract default void apagar() { // método default (Java 8+) System.out.println("Apagando..."); } } // Implementação public class Circulo extends Forma implements Desenhavel { private double raio; public Circulo(double raio) { this.raio = raio; } @Override public double calcularArea() { return Math.PI * raio * raio; } @Override public void desenhar() { System.out.println("Desenhando circulo"); } }
Classe AbstrataInterface
InstanciarNãoNão
Herança/Implement.extends (1 só)implements (várias!)
AtributosQualquer tipoSó constantes (static final)
Métodos concretosSimSó default/static (Java 8+)
UsoCompartilhar código baseDefinir contrato/comportamento
Unidade 4 · Classes e Métodos Genéricos
// Classe genérica — funciona com qualquer tipo T public class Caixa<T> { private T conteudo; public void guardar(T item) { this.conteudo = item; } public T pegar() { return conteudo; } } // Uso Caixa<String> cx1 = new Caixa<>(); cx1.guardar("Olá"); Caixa<Integer> cx2 = new Caixa<>(); cx2.guardar(42); // Método genérico public static <T extends Comparable<T>> T maior(T a, T b) { return a.compareTo(b) >= 0 ? a : b; }

Exercícios Resolvidos
Exercício 5: Qual a diferença entre sobrescrita (override) e sobrecarga (overload)?
Override: redefine método do pai na subclasse (mesmo nome e assinatura). Overload: mesmo nome, assinaturas diferentes na mesma classe.
Override = polimorfismo em tempo de execução. Overload = polimorfismo em tempo de compilação.
Exercício 6: Uma classe pode implementar mais de uma interface?
Sim — Java permite implements múltiplos: class X implements A, B, C.
Isso resolve a limitação da herança simples. Uma classe pode ter um único pai (extends) mas múltiplos contratos (implements).
POO — Módulo 4 · Conceitos Avançados
Unidade 1 · Coleções (Collections)

O Java Collections Framework fornece estruturas de dados dinâmicas prontas. As principais estão no pacote java.util.

import java.util.*; // ArrayList — lista dinâmica ordenada, permite duplicatas List<String> lista = new ArrayList<>(); lista.add("Ana"); lista.add("Bia"); lista.add("Ana"); // duplicata permitida lista.remove("Bia"); lista.get(0); // "Ana" lista.size(); // 2 // Percorrer for (String s : lista) System.out.println(s); // LinkedList — eficiente para inserções/remoções no meio List<Integer> ll = new LinkedList<>(); ll.add(1); ll.add(2); ll.add(3);
Unidade 2 · Conjuntos (Set) e Mapas (Map)
// HashSet — não permite duplicatas, sem ordem garantida Set<String> set = new HashSet<>(); set.add("A"); set.add("B"); set.add("A"); // ignora 2º "A" set.size(); // 2 // TreeSet — sem duplicatas, mantém ordem crescente Set<Integer> ts = new TreeSet<>(); ts.add(30); ts.add(10); ts.add(20); // ts = [10, 20, 30] — sempre ordenado // HashMap — pares chave-valor, sem ordem Map<String, Integer> mapa = new HashMap<>(); mapa.put("Ana", 25); mapa.put("Bia", 30); mapa.get("Ana"); // 25 mapa.containsKey("Bia"); // true // Percorrer mapa for (Map.Entry<String, Integer> e : mapa.entrySet()) { System.out.println(e.getKey() + " = " + e.getValue()); }
ColeçãoDuplicatasOrdemAcessoUso
ArrayListSimInserçãoO(1) por índiceLista geral
LinkedListSimInserçãoO(n)Fila/Deque
HashSetNãoNenhumaO(1)Unicidade
TreeSetNãoCrescenteO(log n)Conjunto ordenado
HashMapChave únicaNenhumaO(1)Dicionário
Unidade 3 · Tratamento de Exceções
// try-catch-finally try { int resultado = 10 / 0; // lança ArithmeticException String s = null; s.length(); // lança NullPointerException } catch (ArithmeticException e) { System.out.println("Erro aritmético: " + e.getMessage()); } catch (NullPointerException e) { System.out.println("Referência nula!"); } finally { System.out.println("Sempre executado!"); // limpar recursos } // Criar exceção personalizada public class SaldoInsuficienteException extends RuntimeException { public SaldoInsuficienteException(double valor) { super("Saldo insuficiente para sacar: R$" + valor); } } // Lançar exceção public void sacar(double valor) { if (valor > saldo) throw new SaldoInsuficienteException(valor); saldo -= valor; }
TipoExemploObrigado tratar?
Checked ExceptionIOException, SQLExceptionSim — try-catch ou throws
Unchecked (Runtime)NullPointerException, ArrayIndexOutOfBoundsNão obrigatório
ErrorOutOfMemoryError, StackOverflowErrorNão trate — grave!
Unidade 4 · Trabalhando com Arquivos e Fluxos
import java.io.*; import java.nio.file.*; // Escrever em arquivo try (BufferedWriter bw = new BufferedWriter(new FileWriter("dados.txt"))) { bw.write("Linha 1\n"); bw.write("Linha 2\n"); } // fecha automaticamente (try-with-resources) // Ler arquivo linha por linha try (BufferedReader br = new BufferedReader(new FileReader("dados.txt"))) { String linha; while ((linha = br.readLine()) != null) { System.out.println(linha); } } // NIO (moderno — Java 7+) Path path = Paths.get("dados.txt"); List<String> linhas = Files.readAllLines(path); Files.write(path, linhas);
⚠ try-with-resources
O bloco try (recurso) fecha automaticamente o recurso ao terminar, mesmo se lançar exceção. Evita vazamento de recursos — sempre prefira para streams e arquivos.

Exercícios Resolvidos
Exercício 7: Quando usar HashSet em vez de ArrayList?
→ Quando precisar garantir unicidade e não importar a ordem.
HashSet rejeita duplicatas automaticamente e busca em O(1). ArrayList permite duplicatas e busca linear O(n). Para CPFs únicos de usuários, por exemplo, HashSet é melhor.
Exercício 8: O que é o bloco finally?
→ Código executado sempre, independente de exceção ou não.
Usado para liberar recursos (fechar arquivos, conexões). Com try-with-resources, o finally explícito ficou menos necessário — o fechamento é automático.
APOO — Módulo 1 · Introdução à Orientação a Objetos
Unidade 1 · Revisão dos Modelos de Processos de Software

Um processo de desenvolvimento de software define as etapas para criar um sistema: análise, projeto, implementação, teste e manutenção. O modelo escolhido impacta custo, prazo e qualidade.

ModeloCaracterísticaVantagemDesvantagem
CascataFases sequenciais, sem voltaSimples, documentadoInflexível a mudanças
IncrementalEntrega parcial em ciclosFeedback cedoPode acumular dívida técnica
EspiralBaseado em riscosGerencia riscosComplexo, caro
Ágil (Scrum/XP)Iterativo, colaborativoAdaptável, rápidoDifícil de escalar
PrototipagemProtótipo rápido para validarRequisitos ficam clarosProtótipo pode virar produto mal feito
⚠ Importante
A escolha do modelo depende do projeto: requisitos estáveis → Cascata. Requisitos mudam → Ágil. Alto risco → Espiral. O modelo OO se encaixa melhor com processos iterativos e incrementais.
Unidade 2 · Conceitos de Orientação a Objetos
Objeto
Entidade com estado (atributos) e comportamento (métodos). Ex: objeto Carro tem cor, velocidade e pode acelerar().
Classe
Descrição/template de um conjunto de objetos com mesmas características. "Planta baixa" do objeto.
Mensagem
Objetos se comunicam enviando mensagens (chamando métodos). Ex: carro.acelerar(50) é uma mensagem.
Responsabilidade
O que um objeto sabe (atributos) e o que ele faz (métodos). Cada objeto tem responsabilidade bem definida.
Exemplo — Modelagem OO
Sistema de biblioteca: objetos Livro (titulo, isbn, estaDisponivel()), Leitor (nome, cpf, pegarEmprestado()), Emprestimo (livro, leitor, dataDevolver()).

Exercícios Resolvidos
Exercício 9: Por que o modelo ágil é mais adequado para a maioria dos projetos OO modernos?
→ POO facilita refatoração e mudanças — encaixa com o ciclo iterativo do ágil.
Encapsulamento e herança permitem mudar partes do sistema sem quebrar outras. No cascata, mudanças são custosas. No ágil + POO, cada iteração entrega novas classes/funcionalidades sem reescrever tudo.
APOO — Módulo 2 · Análise Orientada a Objetos
Unidade 1 · Processos de Análise OO

A análise OO identifica os objetos do mundo real relevantes ao sistema, seus atributos e relacionamentos. O resultado é um modelo de domínio independente de tecnologia.

Passos: (1) Identificar classes candidatas nos requisitos. (2) Filtrar classes relevantes. (3) Definir atributos e operações. (4) Identificar relacionamentos. (5) Verificar com o cliente.

Técnica — CRC Cards (Class-Responsibility-Collaborator)
Cartões físicos para cada classe listando: nome da classe, responsabilidades (o que faz/sabe) e colaboradores (quem usa). Técnica simples e eficaz para análise em equipe.
⚠ Importante
Na análise, foque no O QUE o sistema deve fazer, não no COMO. Evite decisões de implementação (linguagem, banco, framework) nessa fase.
Unidade 2 · UML — Linguagem de Modelagem Unificada

A UML (Unified Modeling Language) é a linguagem padrão para modelar sistemas OO. Não é uma metodologia — é uma notação visual.

Diagrama UMLTipoO que modela
Diagrama de ClassesEstruturalClasses, atributos, métodos e relacionamentos
Diagrama de ObjetosEstruturalInstâncias concretas em momento específico
Diagrama de Casos de UsoComportamentalAtores e funcionalidades do sistema
Diagrama de SequênciaComportamentalTroca de mensagens entre objetos no tempo
Diagrama de AtividadesComportamentalFluxo de trabalho/algoritmo
Diagrama de EstadosComportamentalCiclo de vida de um objeto
Diagrama de Classes — Notação
┌──────────────────────┐ │ Conta │ ← Nome da classe ├──────────────────────┤ │ - numero: String │ ← Atributos (- private, + public, # protected) │ - saldo: double │ │ # titular: String │ ├──────────────────────┤ │ + depositar(v:double) │ ← Métodos │ + sacar(v:double) │ │ + getSaldo(): double │ └──────────────────────┘ Relacionamentos: ────────────── Associação (usa) ──────────────◁ Herança/Generalização (extends) - - - - - - -◁ Realização (implements interface) ◆──────────── Composição (parte não existe sem o todo) ◇──────────── Agregação (parte pode existir sem o todo)
⚠ Composição vs Agregação
Composição: Pedido ◆── ItemPedido. Se o Pedido for deletado, os itens também são. Agregação: Turma ◇── Aluno. Se a Turma acabar, o Aluno ainda existe.

Exercícios Resolvidos
Exercício 10: Qual diagrama UML mostra a ordem das mensagens trocadas entre objetos?
Diagrama de Sequência — eixo vertical = tempo, barras = objetos, setas = mensagens.
Ex: Usuario → Sistema: login(senha) → BD: verificar(usuario, senha) → BD → Sistema: ok → Sistema → Usuario: tela principal.
Exercício 11: Qual a diferença entre composição e agregação no diagrama de classes?
Composição: parte não existe sem o todo (losango cheio). Agregação: parte existe independentemente (losango vazio).
Página não existe sem Livro (composição). Aluno existe sem Turma (agregação).
APOO — Módulo 3 · Projeto Orientado a Objetos
Unidade 1 · Desenho de Projeto OO

O projeto OO transforma o modelo de análise em uma solução técnica. Define como as classes serão implementadas, os padrões usados e a arquitetura do sistema.

Princípios SOLID
Single Responsibility — 1 classe = 1 responsabilidade
Open/Closed — aberto para extensão, fechado para modificação
Liskov — subclasse substituível pela superclasse
Interface Segregation — interfaces coesas e pequenas
Dependency Inversion — dependa de abstrações
Coesão e Acoplamento
Alta coesão: classe tem responsabilidade única e bem definida. Bom!
Baixo acoplamento: classes pouco dependentes entre si. Bom!
Objetivo: maximizar coesão e minimizar acoplamento.
Exemplo — Violação do SRP
Classe RelatorioVendas que busca dados do BD, formata e imprime. Três responsabilidades! Deveria ser: BuscadorVendas + FormataRelatorio + ImpressoraRelatorio.
Exemplo — Open/Closed
Sistema de pagamento: em vez de if (tipo == "pix") ... else if (tipo == "cartao") ..., criar interface Pagamento com pagar(), e cada tipo implementa. Adicionar novo tipo = nova classe, sem mexer no código existente.
Unidade 2 · Padrões GRASP

GRASP (General Responsibility Assignment Software Patterns) são 9 princípios para atribuir responsabilidades a classes e objetos no projeto OO.

Padrão GRASPPergunta que respondeSolução
Especialista (Expert)Quem tem responsabilidade por algo?A classe que tem a informação necessária
Criador (Creator)Quem deve criar instâncias de X?Quem contém, agrega ou usa X
Controlador (Controller)Quem recebe eventos do sistema?Classe controladora (não UI) coordena casos de uso
Baixo AcoplamentoComo reduzir dependências?Atribuir responsabilidade que minimiza ligações
Alta CoesãoComo manter objetos compreensíveis?Responsabilidades relacionadas na mesma classe
PolimorfismoComo tratar alternativas por tipo?Usar polimorfismo em vez de if/switch por tipo
IndireçãoComo evitar acoplamento direto?Introduzir objeto intermediário
Fabricação PuraQuem cuida de responsabilidades de infra?Classe artificial (DAO, Repository) sem domínio
Variações ProtegidasComo proteger de mudanças externas?Interface estável envolve o que varia
Exemplo — Especialista (Expert)
Quem calcula o total do pedido? A classe Pedido — ela tem os itens e preços. Não é a classe Cliente nem a Tela que deve fazer esse cálculo.
Exemplo — Criador (Creator)
Quem cria ItemPedido? A classe Pedido — ela contém/agrega os itens. Logo, Pedido é responsável por criar e gerenciar seus itens.
Exemplo — Fabricação Pura
PedidoDAO (Data Access Object) — classe artificial que cuida de salvar/buscar Pedidos no banco. Não representa nada do domínio, mas evita que Pedido saiba de SQL.

Exercícios Resolvidos
Exercício 12: Pelo padrão Expert, quem deve calcular o subtotal de um ItemPedido?
→ A classe ItemPedido — ela tem preço e quantidade.
Expert: quem tem a informação necessária tem a responsabilidade. ItemPedido tem preco e qtd → calcula subtotal = preco * qtd.
Exercício 13: O que é um DAO e qual padrão GRASP ele representa?
→ DAO é classe artificial para acesso a dados — representa Fabricação Pura.
Sem DAO, a classe de domínio (Pedido) precisaria saber de SQL — alto acoplamento com infra. DAO isola essa responsabilidade.
APOO — Módulo 4 · Prática da Análise e Projeto
Unidade 1 · Ferramentas e Proposta de Projeto

Ferramentas UML populares: Astah (comercial, muito usada em acadêmicos), draw.io (gratuito, web), StarUML, PlantUML (diagramas via texto), Lucidchart (colaborativo).

Processo Completo de Análise e Projeto OO
FaseEntregávelFerramenta/Técnica
Levantamento de RequisitosCasos de uso, histórias de usuárioEntrevistas, diagrama de casos de uso
Análise OOModelo de domínio, diagrama de classes (conceitual)CRC Cards, UML classes
Projeto OODiagrama de classes detalhado, sequência, GRASPAstah, draw.io, SOLID + GRASP
ImplementaçãoCódigo-fonteJava, IDE (Eclipse/IntelliJ)
TestesCasos de teste, relatórioJUnit, testes de integração
Unidade 2 · Implementação OO

Boas práticas de implementação OO: seguir SOLID, aplicar GRASP, usar padrões de projeto (Design Patterns) quando apropriado, e garantir que o código reflita o modelo de domínio.

// Exemplo completo: do modelo ao código // Análise: Sistema de Pedidos // Classes: Pedido, ItemPedido, Produto, Cliente public class Produto { private String nome; private double preco; public Produto(String nome, double preco) { this.nome = nome; this.preco = preco; } public double getPreco() { return preco; } public String getNome() { return nome; } } public class ItemPedido { private Produto produto; private int quantidade; public ItemPedido(Produto produto, int qtd) { this.produto = produto; this.quantidade = qtd; } // Expert: ItemPedido calcula seu próprio subtotal public double getSubtotal() { return produto.getPreco() * quantidade; } } public class Pedido { private List<ItemPedido> itens = new ArrayList<>(); private Cliente cliente; // Creator: Pedido cria seus ItemPedidos public void adicionarItem(Produto p, int qtd) { itens.add(new ItemPedido(p, qtd)); } // Expert: Pedido calcula o total (soma dos subtotais) public double getTotal() { return itens.stream() .mapToDouble(ItemPedido::getSubtotal) .sum(); } }

Exercícios Resolvidos
Exercício 14: No exemplo acima, qual padrão GRASP justifica Pedido::adicionarItem criar ItemPedidos?
Criador (Creator) — Pedido contém/agrega ItemPedidos.
Regra do Creator: B cria A se B contém A, B agrega A, B usa A ou B tem dados para inicializar A. Pedido agrega ItemPedidos → Pedido cria ItemPedidos.
Exercício 15: Por que usar stream().mapToDouble().sum() em vez de um for loop para calcular o total?
→ Mais expressivo, conciso e funcional — o código comunica a intenção claramente.
Streams Java facilitam operações em coleções. mapToDouble converte cada item para double, sum() soma tudo. O resultado é o mesmo do for, mas mais legível e menos propenso a erros.
📝 Cola de Prova — POO & APOO
Os 4 Pilares da POO
PilarPalavra-chave JavaResumo
Encapsulamentoprivate + get/setEsconde estado interno, controla acesso
Herançaextends, superReutiliza código do pai. Java: herança simples
Polimorfismo@OverrideMesmo método, comportamento diferente por tipo
Abstraçãoabstract, interfaceEsconde complexidade, expõe o essencial
Classe Abstrata vs Interface
Classe AbstrataInterface
Herançaextends (1 só)implements (várias)
AtributosQualquerSó static final
Métodos concretosSimdefault/static (Java 8+)
UsoCompartilhar códigoDefinir contrato
Coleções — Escolha Rápida
Precisa de...Use
Lista com duplicatas e acesso por índiceArrayList
Inserção/remoção frequente no meioLinkedList
Elementos únicos, sem ordemHashSet
Elementos únicos, ordenadosTreeSet
Busca por chave (dicionário)HashMap
Dicionário em ordem crescente de chaveTreeMap
GRASP — Resumo dos 9 Padrões
PadrãoIdeia central
ExpertResponsabilidade vai para quem tem a informação
CreatorCria quem contém/agrega/usa
ControllerClasse coordenadora recebe eventos do sistema
Baixo AcoplamentoMinimizar dependências entre classes
Alta CoesãoClasse com responsabilidade única e bem definida
PolimorfismoUsar polimorfismo em vez de if/switch por tipo
IndireçãoIntermediário evita acoplamento direto
Fabricação PuraClasse artificial para responsabilidade de infra (ex: DAO)
Variações ProtegidasInterface estável isola o que muda
Diagramas UML Mais Cobrados
DiagramaPara que serveQuando usar
ClassesEstrutura estática do sistemaSempre — principal diagrama OO
Casos de UsoAtores e funcionalidadesFase de requisitos
SequênciaMensagens entre objetos no tempoDetalhar caso de uso
EstadosCiclo de vida de um objetoObjetos com estados complexos
⭐ Regras de Ouro para a Prova
Regra
Java = herança simples (extends 1). Interfaces = múltiplas (implements vários)
Regra
@Override = sobrescrita (polimorfismo). Overload = mesmo nome, assinatura diferente na mesma classe
Regra
Atributos sempre private. Acesso via getter/setter. Isso é encapsulamento
Regra
Classe abstrata tem código compartilhado. Interface define contrato
Regra
GRASP Expert: responsabilidade vai para quem tem a informação necessária
Regra
GRASP Creator: cria quem contém ou agrega
Regra
Composição ◆ = parte morre com o todo. Agregação ◇ = parte sobrevive sem o todo
Regra
try-with-resources fecha automaticamente — sempre use com arquivos e streams
Regra
SOLID — S: 1 responsabilidade. O: extensível sem modificar. L: subclasse substituível