Top Posts

Como estudar para uma certificação

Continue lendo

Série DesignPattern: Observer

Posted by camilolopes | Posted in DesignPattern, Series | Posted on 21-05-2012

2

Olá Pessoal,

No post de hoje vamos conhecer o padrão comportamental Observer, que tem como objetivo notificar e atualizar classes dependentes de forma automática com base no status. Veremos isso na prática, simulando uma notificação em uma fila por meio de um painel eletrônico.

Lets go…

Observer

Tem como função notificar e atualizar automaticamente classes que dependem do status de outra para fazer uma ação.

Ex.: Quando o estoque do Produto X ficar abaixo de 20, automaticamente notifica o fornecedor.

Essa é uma prática comum em grandes redes de supermercado para manter os produtos de alta demanda sempre disponível para o cliente. Exemplo: “Leite Ninho”. Há uma integração entre o sistema do supermercado e fornecedor, um Observer. Para o fornecedor não ter que ficar todo dia verificando o estoque do supermercado, é melhor que ele seja notificado quando a quantidade de produto estiver próximo de acabar.

Outro exemplo é quando vamos ao supermercado ou ao banco e há um painel eletrônico que nos informa o caixa livre que devemos ir, mas para isso acontecer é preciso que o caixa notifique o painel que ele já está disponível.

No diagrama acima há um esboço do relacionamento entre as classes.

Vamos ver isso na prática. A seguir, o nosso projeto Observer:

 

Primeiramente vamos criar a nossa interface Observer:

 

package br.com.camilolopes.observer;

import br.com.camilolopes.classes.Caixa;

public interface Observer {

void notificaPainel(Caixa caixa);

}

 

Ela tem um método que recebe o caixa disponível.

 

Agora vamos criar a classe Caixa que notifica o Painel quando o status é alterado:

 

Caixa.java

package br.com.camilolopes.classes;

import java.util.HashSet;

import java.util.Set;

import br.com.camilolopes.observer.Observer;

public class Caixa {

private boolean status = false;

//apenas os caixas  que estão funcionando serão os interessados

private Set<Observer> interessados = new HashSet<Observer>();

private String nomeCaixa;

//todo caixa tem um nome + um nro.

public Caixa(String nomeCaixa) {

this.nomeCaixa = nomeCaixa;

}

public boolean isStatus() {

return status;

}

/*

* quando o status é alterado

* notifica o painel

*/

public void setStatus(boolean status) {

this.status = status;

/*

* A mágica está aqui. Notificados o painel que o caixa

* foi alterado. No nosso caso temos apenas um Painel, mas

* poderíamos ter N painéis. Observe quantos painéis temos

* em uma agência bancaria: Um para pessoa física, caixa rápido

* pessoa jurídica etc. Cada um associado a um tipo de caixa (01,02…)

*/

for(Observer interessado : interessados){

interessado.notificaPainel(this);

}

}

public void registraInteressado(Observer interessado){

this.interessados.add(interessado);

}

public String getNomeCaixa() {

return nomeCaixa;

}

public void setNomeCaixa(String nomeCaixa) {

this.nomeCaixa = nomeCaixa;

}

}

 

Precisamos agora criar o interessado em saber quando o status do caixa é alterado, que no nosso caso é o Painel.

 

package br.com.camilolopes.observer;

import br.com.camilolopes.classes.Caixa;

/*

* o interessado em saber a mudança

* do status */

public class Painel01 implements Observer {

 

@Override

public void notificaPainel(Caixa caixa) {

System.out.println(“O ” + caixa.getNomeCaixa() + ” está disponivel.Status alterado para ” + caixa.isStatus());

}

}

Para finalizar, temos uma classe com método main para validar:

 

ObserverMain.java

package br.com.camilolopes.main;

import br.com.camilolopes.classes.Caixa;

import br.com.camilolopes.observer.Painel01;

public class ObserverMain {

public static void main(String[] args) {

Painel01 painel01 = new Painel01();

//poderiamos ter outros paineis para N caixas

//teve o status alterado

Caixa caixa1 = new Caixa(“Caixa 1”);

caixa1.registraInteressado(painel01);

caixa1.setStatus(true);

Caixa caixa2 = new Caixa(“Caixa 2”);

caixa2.registraInteressado(painel01);

//nao teve o status alterado

}

}

 

Rode a aplicação e veja o resultado.

Resultado

Aqui está o nosso resultado. Observe que exibe apenas alteração para o caixa 1, pois este objeto sofreu alteração.

Vou ficando por aqui, espero que tenham gostado do post.

Abraços, see ya.

Série DesignPattern: Facade

Posted by camilolopes | Posted in DesignPattern, Series | Posted on 12-05-2012

0

Olá Pessoal,

No post da série de hoje vamos conhecer o padrão facade, que tem como objetivo simplificar as interações entre o cliente com diversos sistemas, ou seja, para o cliente não ter que ser notificado em cada sistema sobre uma determinada mudança, ele apenas notifica o facade e este vai se encarregar de fazer as devidas notificações. Isso é muito comum no dia-dia, veja como: Uma venda é realizada, então o sistema precisa notificar de imediato o estoque que o produto X agora é Y-1, mas isso de forma simplificada por uma interface. Já pensou se um vendedor tivesse que ir em cada subsistema (estoque, financeiro etc) e informar que acabou de fazer uma venda e o estoque e volume em vendas para o produto XYZ foi alterado? Certamente isso seria ruim, certo? O mais interessante é que através de uma única interface o usuário possa realizar uma ação e o próprio sistema se encarregar de notificar os subsistemas dependentes. É isso que o padrão facade nos possibilita e vamos ver no nosso post de hoje.

Lets go…

Facade

Prover uma interface simplificada para utilização de varias interfaces do subsistema. A ideia é simplificar a iteração entre o cliente e diversos sistemas

Exemplo:

Quando um pedido é emitido precisamos notificar o estoque e financeiro.

Com facade, apenas dizemos o que queremos e o facade vai se encarregar das notificações. É como uma agência de turismo, digo para onde quero ir e eles se encarregam de notificar o hotel, a companhia aérea, o responsável pelo transfer etc.

A ideia do facade é encapsular todos os processos que envolvem a notificação aos demais sistemas. Ou seja, a forma que o agente de viagem notifica os parceirosda agência é encapsulada. Este pode ser por e-mail, telefone, via um sistema integrado etc. Isso o cliente final não sabe e também não importa muito, desde que a notificação aconteça.

Desenvolvimento

A seguir veremos um exemplo prático com facade, assim colocamos a teoria em prática. Primeiramente criamos o projeto a seguir:

Agora vamos criar três classes: Cliente, CiaArea, Hotel. A ideia é simular que o cliente solicitou para um agente de viagem um reserva e o agente fez uma reserva no hotel e na companhia aérea, ou seja, o agente de viagem foi responsável pela notificação. Então já sabemos quem é o nosso facade.

Cliente.java

Essa é a nossa classe cliente, nada de especial nela.

 package br.com.camilolopes.classes;

public class Cliente {

private String nome;

private String sobreNome;

private int idade;

public Cliente(String nome, String sobreNome, int idade) {

super();

this.nome = nome;

this.sobreNome = sobreNome;

this.idade = idade;

}

public String getNome() {

return nome;

}

public void setNome(String nome) {

this.nome = nome;

}

public String getSobreNome() {

return sobreNome;

}

public void setSobreNome(String sobreNome) {

this.sobreNome = sobreNome;

}

public int getIdade() {

return idade;

}

public void setIdade(int idade) {

this.idade = idade;

}

}

 CiaArea

Classe que representa as informações para reserva de um voo.

package br.com.camilolopes.classes;

public class CiaAerea {

private String nomeCia;

public CiaAerea(String nomeCia) {

super();

this.nomeCia = nomeCia;

}

public String getNomeCia() {

return nomeCia;

}

public void setNomeCia(String nomeCia) {

this.nomeCia = nomeCia;

}

public void reservaVoo(String nome, String sobreNome) {

System.out.println(“Voo reservado na Cia ” + nomeCia);

System.out.println(“para ” + nome + ” ” + sobreNome);

}

}

Hotel.java

Faz a reserva no hotel, nada de especial aqui também.

package br.com.camilolopes.classes;

public class Hotel {

private String nome;

private double valorDiaria;

public Hotel(String nome, double valorDiaria) {

super();

this.nome = nome;

this.valorDiaria = valorDiaria;

}

public String getNome() {

return nome;

}

public void setNome(String nome) {

this.nome = nome;

}

public double getValorDiaria() {

return valorDiaria;

}

public void setValorDiaria(double valorDiaria) {

this.valorDiaria = valorDiaria;

}

public void registraReserva(String nomeCliente, String sobreNomeCliente) {

System.out.println(“o Hotel ” + this.nome + ” informa que a reserva para “);

System.out.println(nomeCliente + ” ” + sobreNomeCliente + ” foi realizada com sucesso”);

}

}

Agora já temos o “pulo do gato”, nosso facade, que chamei de AgenciaFacade por questões didáticas:

AgenciaFacade.java

package br.com.camilolopes.facade;

import br.com.camilolopes.classes.CiaAerea;

import br.com.camilolopes.classes.Cliente;

import br.com.camilolopes.classes.Hotel;

/*

* A classe facade que é responsável por

* notificar as demais classes

*/

public class AgenciaFacade {

/*observe que a class facade é do tipo de relacionamento HAS-An

* com as classes que vão receber a notificação

*/

private Hotel hotel;

private CiaAerea ciaAerea

public AgenciaFacade(Hotel hotel, CiaAerea ciaAerea) {

super();

this.hotel = hotel;

this.ciaAerea = ciaAerea;

}

//aqui que acontece as notificações para  as dependências

public void registraViagem(Cliente cliente){

this.hotel.registraReserva(cliente.getNome(),cliente.getSobreNome());

this.ciaAerea.reservaVoo(cliente.getNome(),cliente.getSobreNome());

}

public Hotel getHotel() {

return hotel;

}

public void setHotel(Hotel hotel) {

this.hotel = hotel;

}

public CiaAerea getCiaAerea() {

return ciaAerea;

}

 public void setCiaAerea(CiaAerea ciaAerea) {

this.ciaAerea = ciaAerea;

}

AgenciaMain.java

package br.com.camilolopes.main;

import br.com.camilolopes.classes.CiaAerea;

import br.com.camilolopes.classes.Cliente;

import br.com.camilolopes.classes.Hotel;

import br.com.camilolopes.facade.AgenciaFacade;

public class AgenciaMain {

public static void main(String[] args) {

Cliente cliente = new Cliente(“Camilo”, “Lopes”, 25);

Hotel hotel = new Hotel(“Pijamas”, 150.00);

CiaAerea ciaAerea = new CiaAerea(“VaEmbora”);

//o facade sabe qual hotel e ciaAerea notificar

AgenciaFacade agencia = new AgenciaFacade(hotel, ciaAerea);

//informando para agencia o cliente que deseja viajar

agencia.registraViagem(cliente);

}

}

 Uma classe Java que criei apenas para testar a funcionalidade. Claro que podemos fazer essa validação usando unit test, mas preferi fazer com o método main. Assim, aqueles que não sabem usar unit test não ficam limitados.

Resultado

Rode aplicação e veja o resultado:

Pronto! Facade implementado como esperado, de maneira fácil que nem acreditamos que é tão simples assim. Mas é isso ai pessoal, espero que tenham gostado do post. Vou ficando por aqui.

Abracos, see ya!