SlideShare uma empresa Scribd logo
SOLID no Android
Android Dev Conference 2016
Esses são os slides que apresentei no
Android Dev Conference 2016.
Acreditei que por não conter nenhum
“voice over” seria justo fazer pequenas
adaptações para melhor entendimento,
espero que seja útil para você!
Twitter: http://twitter.com/marcellogalhard
LinkedIn: https://www.linkedin.com/in/marcellogalhardo
Github: https://github.com/marcellogalhardo
E-mail: marcello.galhardo@gmail.com
Medium: https://medium.com/@marcellogalhardo
Contatos.
Marcello Galhardo
Desenvolvedor Android
Android DevConference - SOLID no Android
Android DevConference - SOLID no Android
Criado em 2000 por
Robert C. Martin; 5
princípios de
programação.
"Paciência você deve
ter meu jovem
Padawan."
"Quem planta
gambiarras, colhe
bugs."
http://martinfowler.com/bliki/DesignStaminaHypothesis.html
Trade Off Qualidade
Princípio da
Responsabilidade
Única
Single Responsibility Principle
"Uma classe deve ter
um, e somente um,
motivo para mudar."
Violação.
public class Produto {
private String descricao;
private int quantidade;
private long preco;
// ... getters/setters
}
public class Pedido {
private int numeroDoPedido;
private List<Produto> produtos = new ArrayList<>();
// ... getters/setters
}
public class PedidoRecyclerAdapter
extends RecyclerView.Adapter<PedidoRecyclerAdapter.ViewHolder> {
private List<Pedido> pedidos;
public OrderRecyclerAdapter(List<Pedido> pedidos) {
this.pedidos = pedidos;
}
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.item_pedidos, parent, false);
return new ViewHolder(v);
}
@Override public void onBindViewHolder(ViewHolder holder, int position) {
// TODO: Faz o vínculo entre o modelo e a view
}
@Override public int getItemCount() {
return pedidos.size();
}
// ... ViewHolder e métodos
}
@Override public void onBindViewHolder(ViewHolder holder, int position) {
Pedido pedido = items.get(position);
holder.numeroDoPedido.setText(pedido.getNumeroDoPedido().toString());
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US);
String valorTotal = formatter.format(total);
holder.valorTotalDoPedido.setText(valorTotal);
holder.itemView.setTag(pedido);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView numeroDoPedido;
public TextView valorTotalDoPedido;
// FindViews.
}
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US);
String valorTotal = formatter.format(total);
holder.valorTotalDoPedido.setText(valorTotal);
Solução.
public class Pedido {
private int numeroDoPedido;
private List<Produto> produtos = new ArrayList<>();
// ... getters/setters
public long getValorTotalDoPedido() {
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
return total;
}
public String getValorTotalDoPedidoFormatado() {
long total = getValorTotalDoPedido();
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US);
String valorTotal = formatter.format(total);
return valorTotal;
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Pedido pedido = items.get(position);
holder.numeroDoPedido.setText(pedido.getNumeroDoPedidoFormatado());
holder.valorTotalDoPedido.setText(pedido.getValorTotalDoPedidoFormato());
holder.itemView.setTag(pedido);
}
Rigidez.
Princípio do
Aberto e Fechado
Open/Closed Principle
"Você deve ser capaz de
estender um
comportamento de uma
classe, sem modificá-lo."
Violação.
public class Pedido {
private int numeroDoPedido;
private List<Produto> produtos = new ArrayList<>();
// ... getters/setters
public long getValorTotalDoPedido() {
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
return total;
}
public String getValorTotalDoPedidoFormatado() {
long total = getValorTotalDoPedido();
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US);
String valorTotal = formatter.format(total);
return valorTotal;
}
}
private static final int SEM_DESCONTO = 0;
private static final int DESCONTO_10_POR_CENTO = 1;
private static final int DESCONTO_15_POR_CENTO = 2;
private int tipoDeDesconto;
public long getValorTotalDoPedido() {
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
if (tipoDeDesconto == DESCONTO_10_POR_CENTO) {
long descontoDe10PorCento = total * 0.1;
total += descontoDe10PorCento;
} else if (tipoDeDesconto == DESCONTO_15_POR_CENTO ) {
long descontoDe15PorCento = total * 0.15;
total += descontoDe15PorCento;
}
return total;
}
public class Pedido {
private static final int SEM_DESCONTO = 0;
private static final int DESCONTO_10_POR_CENTO = 1;
private static final int DESCONTO_15_POR_CENTO = 2;
private int numeroDoPedido;
private List<Produto> produtos = new ArrayList<>();
private int tipoDeDesconto;
// ... getters/setters
public long getValorTotalDoPedido() {
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
if (tipoDeDesconto == DESCONTO_10_POR_CENTO) {
long descontoDe10PorCento = total * 0.1;
total += descontoDe10PorCento;
} else if (tipoDeDesconto == DESCONTO_15_POR_CENTO ) {
long descontoDe15PorCento = total * 0.15;
total += descontoDe15PorCento;
}
return total;
}
public String getValorTotalDoPedidoFormatado() {
long total = getValorTotalDoPedido();
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US);
String valorTotal = formatter.format(total);
return valorTotal;
}
}
private static final int SEM_DESCONTO = 0;
private static final int DESCONTO_10_POR_CENTO = 1;
private static final int DESCONTO_15_POR_CENTO = 2;
private static final int DESCONTO_20_POR_CENTO = 3;
private static final int DESCONTO_25_POR_CENTO = 4;
private int tipoDeDesconto;
public long getValorTotalDoPedido() {
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
if (tipoDeDesconto == DESCONTO_10_POR_CENTO) {
long descontoDe10PorCento = total * 0.1;
total += descontoDe10PorCento;
} else if (tipoDeDesconto == DESCONTO_15_POR_CENTO) {
long descontoDe15PorCento = total * 0.15;
total += descontoDe15PorCento;
} else if (tipoDeDesconto == DESCONTO_20_POR_CENTO) {
long descontoDe20PorCento = total * 0.20;
total += descontoDe20PorCento;
} else if (tipoDeDesconto == DESCONTO_25_POR_CENTO) {
long descontoDe25PorCento = total * 0.25;
total += descontoDe25PorCento;
}
return total;
}
Solução.
public interface Desconto {
long calculaDesconto(long valor);
}
public interface Desconto {
long calculaDesconto(long valor);
}
// Padrão de Projeto: Objeto Nulo.
public class SemDesconto implements Desconto {
public long calculaDesconto(long valor) {
return 0;
}
}
public class DescontoDe10PorCento implements Desconto {
public long calculaDesconto(long valor) {
return valor * 0.1;
}
}
public class DescontoDe15PorCento implements Desconto {
public long calculaDesconto(long valor) {
return valor * 0.15;
}
}
// Outros descontos.
Objeto Nulo
private Desconto desconto = new SemDesconto();
public long getValorTotalDoPedido() {
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
// Não é necessário verificar se o desconto é null, pois
// sempre existirá um desconto vazio: SemDesconto.
desconto = desconto.calculaDesconto(total);
return total + desconto;
}
public class Pedido {
private int numeroDoPedido;
private List<Produto> produtos = new ArrayList<>();
private Desconto desconto = new SemDesconto();
// ... getters/setters
public long getValorTotalDoPedido() {
long total = 0;
for (Produto produto : pedido.getProdutos()) {
total += produto.getPreco();
}
desconto = desconto.calculaDesconto(total);
return total + desconto;
}
public String getValorTotalDoPedidoFormatado() {
long total = getValorTotalDoPedido();
NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US);
String valorTotal = formatter.format(total);
return valorTotal;
}
}
Princípio da
Substituição de
Liskov
Liskov Substitution Principle
"Classes derivadas
devem ser
substituíveis por
suas classes base."
Violação.
// Violação do Princípio de Liskov.
public interface Carro {
public void partidaNoMotor();
}
public class Ferrari implements Carro {
@Override public double partidaNoMotor() {
// TODO: Lógica.
}
}
public class Tesla implements Carro {
@Override public void ligaCarro() {
// TODO: Lógica.
}
@Override public double partidaNoMotor() {
// TODO: Lógica.
}
}
// Iniciar Carro.
public void iniciarPartidaDeCarro(Carro carro) {
carro.partidaNoMotor();
}
// "Tentativa de correção" do princípio de Liskov.
public void iniciarPartidaDeCarro(Carro carro) {
if (carro instanceof Tesla) {
Tesla tesla = (Tesla) carro;
tesla.ligaCarro();
}
carro.partidaNoMotor();
}
Solução.
// Correção do Princípio de Liskov
public interface Carro {
public void partidaNoMotor();
}
public class Ferrari implements Carro {
@Override public double partidaNoMotor() {
// TODO: Implementação.
}
}
public class Tesla implements Carro {
// Implementação do ligaCarro();
@Override public double partidaNoMotor() {
if (!estaDescarregado) {
ligaCarro();
}
// TODO: Implementação.
}
}
// Iniciar Carro.
public void iniciarPartidaDeCarro(Carro carro) {
carro.partidaNoMotor();
}
Princípio da
Segregação de
Interface
Interface Segregation Principle
"Muitas interfaces
específicas são
melhores do que
uma interface
única."
Violação.
public interface OnClickListener {
void onClick(View v);
void onLongClick(View v);
void onTouch(View v, MotionEvent event);
}
// Violação do Princípio da Segregação de Interfaces
Button botao = (Button) findViewById(R.id.botao);
botao.setOnClickListener(new View.OnClickListener {
public void onClick(View v) {
// TODO: Faz algo bem legal...
}
public void onLongClick(View v) {
// Não precisamos disso.
}
public void onTouch(View v, MotionEvent event) {
// Disso também não.
}
});
Solução.
// Correção do Princípio da Segregação de Interfaces.
public interface OnClickListener {
void onClick(View v);
}
public interface OnLongClickListener {
void onLongClick(View v);
}
public interface OnTouchListener {
void onTouch(View v, MotionEvent event);
}
Princípio da
Inversão da
Dependência
Dependency Inversion Principle
"Dependa de uma
abstração e não de
uma
implementação."
Violação.
// Violação do Princípio da Inversão de Dependência.
class Presenter {
private final UsuarioRepositorio usuarioRepositorio
= new UsuarioRepositorio();
// TODO: Implementação diversas.
}
class UsuarioRepositorio {
public getUsuario() {
// TODO: Recupera o usuário conectado.
}
}
Solução.
// Correção do Princípio da Inversão de Dependência.
class Presenter {
private final UsuarioRepositorio usuarioRepositorio;
@Inject
public Presenter(UsuarioRepositorio usuarioRepositorio) {
this.usuarioRepositorio = usuarioRepositorio;
}
// TODO: Implementação diversas.
}
interface UsuarioRepositorio {
Usuario getUsuario();
}
class UsuarioManager implements UsuarioRepositorio {
@Override
public getUsuario() {
// TODO: Recupera o usuário conectado.
}
}
Android DevConference - SOLID no Android

Mais conteúdo relacionado

KEY
Test-Driven Development e sua influência no design
PPTX
PDF
Design Patterns na Programação de Jogo
PDF
Android DevConference - Live code with Kotlin: construindo o primeiro app usa...
PDF
Android DevConference - Refactoring for RxJava
PDF
Android DevConference - Indo além com automação de testes de apps Android
PDF
Dominando o Data Binding no Android
PDF
Test-Driven Development e sua influência no design
Design Patterns na Programação de Jogo
Android DevConference - Live code with Kotlin: construindo o primeiro app usa...
Android DevConference - Refactoring for RxJava
Android DevConference - Indo além com automação de testes de apps Android
Dominando o Data Binding no Android

Semelhante a Android DevConference - SOLID no Android (19)

PDF
Combatendo code smells em aplicações Java
PPTX
Design patterns
PPT
Introdução à análise orientada a objetos parte 2
DOCX
PDF
Android Dev Conference 2017 - Arquitetura para projetos Android
PDF
Refactoring
ODP
Clean code
PDF
qualidade de código: boas práticas, princípios e padrões
PDF
Refatoração e Boas Práticas no Desenvolvimento de Software com a Linguagem Ja...
PPT
Introdução à análise orientada a objetos parte 1
PPT
Introdução à análise orientada a objetos parte 1
PPT
Encapsulamento em oo
PPSX
TDD e Clean Code
PDF
principios_SOLID_resumo.pdf
KEY
Conexão Java 2012 - Orientação a Objetos das Galáxias
PPTX
Código Limpo Dual
PDF
Princípios de projeto e boas práticas de programação em Java - Márcio Torres
KEY
Codifique melhor
PPT
Combatendo code smells em aplicações Java
Design patterns
Introdução à análise orientada a objetos parte 2
Android Dev Conference 2017 - Arquitetura para projetos Android
Refactoring
Clean code
qualidade de código: boas práticas, princípios e padrões
Refatoração e Boas Práticas no Desenvolvimento de Software com a Linguagem Ja...
Introdução à análise orientada a objetos parte 1
Introdução à análise orientada a objetos parte 1
Encapsulamento em oo
TDD e Clean Code
principios_SOLID_resumo.pdf
Conexão Java 2012 - Orientação a Objetos das Galáxias
Código Limpo Dual
Princípios de projeto e boas práticas de programação em Java - Márcio Torres
Codifique melhor
Anúncio

Mais de iMasters (20)

PPTX
O que você precisa saber para modelar bancos de dados NoSQL - Dani Monteiro
PDF
Postgres: wanted, beloved or dreaded? - Fabio Telles
PPTX
Por que minha query esta lenta? - Suellen Moraes
PPTX
Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...
PDF
ORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalves
PPTX
SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...
PDF
Arquitetando seus dados na prática para a LGPD - Alessandra Martins
PDF
O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...
PDF
Desenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana Chahoud
PDF
Use MDD e faça as máquinas trabalharem para você - Andreza Leite
PDF
Entendendo os porquês do seu servidor - Talita Bernardes
PDF
Backend performático além do "coloca mais máquina lá" - Diana Arnos
PPTX
Dicas para uma maior performance em APIs REST - Renato Groffe
PPTX
7 dicas de desempenho que equivalem por 21 - Danielle Monteiro
PDF
Quem se importa com acessibilidade Web? - Mauricio Maujor
PDF
Service Mesh com Istio e Kubernetes - Wellington Figueira da Silva
PDF
Erros: Como eles vivem, se alimentam e se reproduzem? - Augusto Pascutti
PDF
Elasticidade e engenharia de banco de dados para alta performance - Rubens G...
PDF
Construindo aplicações mais confiantes - Carolina Karklis
PDF
Monitoramento de Aplicações - Felipe Regalgo
O que você precisa saber para modelar bancos de dados NoSQL - Dani Monteiro
Postgres: wanted, beloved or dreaded? - Fabio Telles
Por que minha query esta lenta? - Suellen Moraes
Relato das trincheiras: o dia a dia de uma consultoria de banco de dados - Ig...
ORMs heróis ou vilões dentro da arquitetura de dados? - Otávio gonçalves
SQL e NoSQL trabalhando juntos: uma comparação para obter o melhor de ambos -...
Arquitetando seus dados na prática para a LGPD - Alessandra Martins
O papel do DBA no mundo de ciência de dados e machine learning - Mauro Pichil...
Desenvolvimento Mobile Híbrido, Nativo ou Web: Quando usá-los - Juliana Chahoud
Use MDD e faça as máquinas trabalharem para você - Andreza Leite
Entendendo os porquês do seu servidor - Talita Bernardes
Backend performático além do "coloca mais máquina lá" - Diana Arnos
Dicas para uma maior performance em APIs REST - Renato Groffe
7 dicas de desempenho que equivalem por 21 - Danielle Monteiro
Quem se importa com acessibilidade Web? - Mauricio Maujor
Service Mesh com Istio e Kubernetes - Wellington Figueira da Silva
Erros: Como eles vivem, se alimentam e se reproduzem? - Augusto Pascutti
Elasticidade e engenharia de banco de dados para alta performance - Rubens G...
Construindo aplicações mais confiantes - Carolina Karklis
Monitoramento de Aplicações - Felipe Regalgo
Anúncio

Último (19)

PPTX
Como-se-implementa-um-softwareeeeeeeeeeeeeeeeeeeeeeeee.pptx
PDF
Fundamentos de gerenciamento de ordens e planejamento no SAP TransportationMa...
PPTX
Informática Aplicada Informática Aplicada Plano de Ensino - estudo de caso NR...
PPTX
Aula 18 - Manipulacao De Arquivos python
PDF
20250805_ServiceNow e a Arquitetura Orientada a Serviços (SOA) A Base para Ap...
PDF
Apple Pippin Uma breve introdução. - David Glotz
PDF
COBITxITIL-Entenda as diferença em uso governança TI
PPTX
BANCO DE DADOS - AULAS INICIAIS-sgbd.pptx
PPTX
Aula16ManipulaçãoDadosssssssssssssssssssssssssssss
PPTX
Gestao-de-Bugs-em-Software-Introducao.pptxxxxxxxx
PDF
Fullfilment AI - Forum ecommerce 2025 // Distrito e Total Express
PDF
Gestão de transportes básica no SAP S/4HANA, S4611 Col20
PDF
Otimizador de planejamento e execução no SAP Transportation Management, TM120...
PDF
Custos e faturamento no SAP S/4HANA Transportation Management, S4TM3 Col26
PPTX
Programação - Linguagem C - Variáveis, Palavras Reservadas, tipos de dados, c...
PDF
Custos e liquidação no SAP Transportation Management, TM130 Col18
PDF
Aula04-Academia Heri- Tecnologia Geral 2025
PDF
Processos na gestão de transportes, TM100 Col18
PDF
Mergulho profundo técnico para gestão de transportes no SAP S/4HANA, S4TM6 Col14
Como-se-implementa-um-softwareeeeeeeeeeeeeeeeeeeeeeeee.pptx
Fundamentos de gerenciamento de ordens e planejamento no SAP TransportationMa...
Informática Aplicada Informática Aplicada Plano de Ensino - estudo de caso NR...
Aula 18 - Manipulacao De Arquivos python
20250805_ServiceNow e a Arquitetura Orientada a Serviços (SOA) A Base para Ap...
Apple Pippin Uma breve introdução. - David Glotz
COBITxITIL-Entenda as diferença em uso governança TI
BANCO DE DADOS - AULAS INICIAIS-sgbd.pptx
Aula16ManipulaçãoDadosssssssssssssssssssssssssssss
Gestao-de-Bugs-em-Software-Introducao.pptxxxxxxxx
Fullfilment AI - Forum ecommerce 2025 // Distrito e Total Express
Gestão de transportes básica no SAP S/4HANA, S4611 Col20
Otimizador de planejamento e execução no SAP Transportation Management, TM120...
Custos e faturamento no SAP S/4HANA Transportation Management, S4TM3 Col26
Programação - Linguagem C - Variáveis, Palavras Reservadas, tipos de dados, c...
Custos e liquidação no SAP Transportation Management, TM130 Col18
Aula04-Academia Heri- Tecnologia Geral 2025
Processos na gestão de transportes, TM100 Col18
Mergulho profundo técnico para gestão de transportes no SAP S/4HANA, S4TM6 Col14

Android DevConference - SOLID no Android

  • 1. SOLID no Android Android Dev Conference 2016
  • 2. Esses são os slides que apresentei no Android Dev Conference 2016. Acreditei que por não conter nenhum “voice over” seria justo fazer pequenas adaptações para melhor entendimento, espero que seja útil para você!
  • 3. Twitter: http://twitter.com/marcellogalhard LinkedIn: https://www.linkedin.com/in/marcellogalhardo Github: https://github.com/marcellogalhardo E-mail: marcello.galhardo@gmail.com Medium: https://medium.com/@marcellogalhardo Contatos.
  • 7. Criado em 2000 por Robert C. Martin; 5 princípios de programação.
  • 8. "Paciência você deve ter meu jovem Padawan."
  • 12. "Uma classe deve ter um, e somente um, motivo para mudar."
  • 14. public class Produto { private String descricao; private int quantidade; private long preco; // ... getters/setters } public class Pedido { private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>(); // ... getters/setters }
  • 15. public class PedidoRecyclerAdapter extends RecyclerView.Adapter<PedidoRecyclerAdapter.ViewHolder> { private List<Pedido> pedidos; public OrderRecyclerAdapter(List<Pedido> pedidos) { this.pedidos = pedidos; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(context); View v = inflater.inflate(R.layout.item_pedidos, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder holder, int position) { // TODO: Faz o vínculo entre o modelo e a view } @Override public int getItemCount() { return pedidos.size(); } // ... ViewHolder e métodos }
  • 16. @Override public void onBindViewHolder(ViewHolder holder, int position) { Pedido pedido = items.get(position); holder.numeroDoPedido.setText(pedido.getNumeroDoPedido().toString()); long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); holder.valorTotalDoPedido.setText(valorTotal); holder.itemView.setTag(pedido); } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView numeroDoPedido; public TextView valorTotalDoPedido; // FindViews. }
  • 17. long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); holder.valorTotalDoPedido.setText(valorTotal);
  • 19. public class Pedido { private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>(); // ... getters/setters public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } return total; } public String getValorTotalDoPedidoFormatado() { long total = getValorTotalDoPedido(); NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); return valorTotal; } }
  • 20. @Override public void onBindViewHolder(ViewHolder holder, int position) { Pedido pedido = items.get(position); holder.numeroDoPedido.setText(pedido.getNumeroDoPedidoFormatado()); holder.valorTotalDoPedido.setText(pedido.getValorTotalDoPedidoFormato()); holder.itemView.setTag(pedido); }
  • 22. Princípio do Aberto e Fechado Open/Closed Principle
  • 23. "Você deve ser capaz de estender um comportamento de uma classe, sem modificá-lo."
  • 25. public class Pedido { private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>(); // ... getters/setters public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } return total; } public String getValorTotalDoPedidoFormatado() { long total = getValorTotalDoPedido(); NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); return valorTotal; } }
  • 26. private static final int SEM_DESCONTO = 0; private static final int DESCONTO_10_POR_CENTO = 1; private static final int DESCONTO_15_POR_CENTO = 2; private int tipoDeDesconto; public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } if (tipoDeDesconto == DESCONTO_10_POR_CENTO) { long descontoDe10PorCento = total * 0.1; total += descontoDe10PorCento; } else if (tipoDeDesconto == DESCONTO_15_POR_CENTO ) { long descontoDe15PorCento = total * 0.15; total += descontoDe15PorCento; } return total; }
  • 27. public class Pedido { private static final int SEM_DESCONTO = 0; private static final int DESCONTO_10_POR_CENTO = 1; private static final int DESCONTO_15_POR_CENTO = 2; private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>(); private int tipoDeDesconto; // ... getters/setters public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } if (tipoDeDesconto == DESCONTO_10_POR_CENTO) { long descontoDe10PorCento = total * 0.1; total += descontoDe10PorCento; } else if (tipoDeDesconto == DESCONTO_15_POR_CENTO ) { long descontoDe15PorCento = total * 0.15; total += descontoDe15PorCento; } return total; } public String getValorTotalDoPedidoFormatado() { long total = getValorTotalDoPedido(); NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); return valorTotal; } }
  • 28. private static final int SEM_DESCONTO = 0; private static final int DESCONTO_10_POR_CENTO = 1; private static final int DESCONTO_15_POR_CENTO = 2; private static final int DESCONTO_20_POR_CENTO = 3; private static final int DESCONTO_25_POR_CENTO = 4; private int tipoDeDesconto; public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } if (tipoDeDesconto == DESCONTO_10_POR_CENTO) { long descontoDe10PorCento = total * 0.1; total += descontoDe10PorCento; } else if (tipoDeDesconto == DESCONTO_15_POR_CENTO) { long descontoDe15PorCento = total * 0.15; total += descontoDe15PorCento; } else if (tipoDeDesconto == DESCONTO_20_POR_CENTO) { long descontoDe20PorCento = total * 0.20; total += descontoDe20PorCento; } else if (tipoDeDesconto == DESCONTO_25_POR_CENTO) { long descontoDe25PorCento = total * 0.25; total += descontoDe25PorCento; } return total; }
  • 30. public interface Desconto { long calculaDesconto(long valor); }
  • 31. public interface Desconto { long calculaDesconto(long valor); } // Padrão de Projeto: Objeto Nulo. public class SemDesconto implements Desconto { public long calculaDesconto(long valor) { return 0; } } public class DescontoDe10PorCento implements Desconto { public long calculaDesconto(long valor) { return valor * 0.1; } } public class DescontoDe15PorCento implements Desconto { public long calculaDesconto(long valor) { return valor * 0.15; } } // Outros descontos.
  • 33. private Desconto desconto = new SemDesconto(); public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } // Não é necessário verificar se o desconto é null, pois // sempre existirá um desconto vazio: SemDesconto. desconto = desconto.calculaDesconto(total); return total + desconto; }
  • 34. public class Pedido { private int numeroDoPedido; private List<Produto> produtos = new ArrayList<>(); private Desconto desconto = new SemDesconto(); // ... getters/setters public long getValorTotalDoPedido() { long total = 0; for (Produto produto : pedido.getProdutos()) { total += produto.getPreco(); } desconto = desconto.calculaDesconto(total); return total + desconto; } public String getValorTotalDoPedidoFormatado() { long total = getValorTotalDoPedido(); NumberFormat formatter = NumberFormat.getCurrencyInstance(Locale.US); String valorTotal = formatter.format(total); return valorTotal; } }
  • 38. // Violação do Princípio de Liskov. public interface Carro { public void partidaNoMotor(); } public class Ferrari implements Carro { @Override public double partidaNoMotor() { // TODO: Lógica. } } public class Tesla implements Carro { @Override public void ligaCarro() { // TODO: Lógica. } @Override public double partidaNoMotor() { // TODO: Lógica. } } // Iniciar Carro. public void iniciarPartidaDeCarro(Carro carro) { carro.partidaNoMotor(); }
  • 39. // "Tentativa de correção" do princípio de Liskov. public void iniciarPartidaDeCarro(Carro carro) { if (carro instanceof Tesla) { Tesla tesla = (Tesla) carro; tesla.ligaCarro(); } carro.partidaNoMotor(); }
  • 41. // Correção do Princípio de Liskov public interface Carro { public void partidaNoMotor(); } public class Ferrari implements Carro { @Override public double partidaNoMotor() { // TODO: Implementação. } } public class Tesla implements Carro { // Implementação do ligaCarro(); @Override public double partidaNoMotor() { if (!estaDescarregado) { ligaCarro(); } // TODO: Implementação. } } // Iniciar Carro. public void iniciarPartidaDeCarro(Carro carro) { carro.partidaNoMotor(); }
  • 43. "Muitas interfaces específicas são melhores do que uma interface única."
  • 45. public interface OnClickListener { void onClick(View v); void onLongClick(View v); void onTouch(View v, MotionEvent event); }
  • 46. // Violação do Princípio da Segregação de Interfaces Button botao = (Button) findViewById(R.id.botao); botao.setOnClickListener(new View.OnClickListener { public void onClick(View v) { // TODO: Faz algo bem legal... } public void onLongClick(View v) { // Não precisamos disso. } public void onTouch(View v, MotionEvent event) { // Disso também não. } });
  • 48. // Correção do Princípio da Segregação de Interfaces. public interface OnClickListener { void onClick(View v); } public interface OnLongClickListener { void onLongClick(View v); } public interface OnTouchListener { void onTouch(View v, MotionEvent event); }
  • 50. "Dependa de uma abstração e não de uma implementação."
  • 52. // Violação do Princípio da Inversão de Dependência. class Presenter { private final UsuarioRepositorio usuarioRepositorio = new UsuarioRepositorio(); // TODO: Implementação diversas. } class UsuarioRepositorio { public getUsuario() { // TODO: Recupera o usuário conectado. } }
  • 54. // Correção do Princípio da Inversão de Dependência. class Presenter { private final UsuarioRepositorio usuarioRepositorio; @Inject public Presenter(UsuarioRepositorio usuarioRepositorio) { this.usuarioRepositorio = usuarioRepositorio; } // TODO: Implementação diversas. } interface UsuarioRepositorio { Usuario getUsuario(); } class UsuarioManager implements UsuarioRepositorio { @Override public getUsuario() { // TODO: Recupera o usuário conectado. } }