Série DesignPattern: Visitor

Olá Pessoal,

Chegamos ao último post da Série DesignPattern. E hoje vamos conhecer o padrão de comportamento Visitor. Em resumo, o Visitor permite atualizarmos uma coleção de objetos de acordo com o tipo de cada objeto contido na coleção. Na prática você tem uma lista com vários objetos com tipos diferentes e cada um sofrerá um tipo de atualização. Neste post vamos ver isso, praticando com o conceito de contas bancárias.

Lets go…

Visitor

Permite atualizações específicas em uma coleção de objetos de acordo com o tipo particular de cada objeto.

Exemplo: posso ter uma lista de contas: poupança, corrente, digital etc. O banco pode querer atualizar a taxa para o valor X com base no tipo. Se for poupança, a taxa de rendimento será 0.5%, se for corrente será 0.0%. No diagrama a seguir temos uma ideia do Visitor. Fiz com base no nosso exemplo.

Praticando

A seguir teremos o projeto e a implementação. Como sempre, há comentários chamando atenção para o que considerei importante.  Crie um projeto conforme a imagem seguir:

Criando o Visitor AtualizadorConta (interface)

Primeiramente vamos criar o nosso Visitor, pois ele define os objetos responsáveis pelas atualizações:

package br.com.camilolopes.visitor;

import br.com.camilolopes.classes.ContaCorrente;

import br.com.camilolopes.classes.ContaPoupanca;

/*O tal do Visitor que define os objetos responsaveis

* pelas atualizações: Conta Corrente & Conta Poupança

*/

public interface AtualizadorConta {

void atualiza(ContaCorrente contaCorrente);

void atualiza(ContaPoupanca contaPoupanca);

}

Claro que ainda não temos as classes ContaCorrente e ContaPoupanca. Portanto, vamos criá-las em alguns minutos.  Mas antes precisamos criar a nossa classe abstract Conta e a interface Atualizável, que representa um Element, ou seja, sabemos os objetos que podem ser atualizados pelo Visitor.

Atualizavel.java (interface)

package br.com.camilolopes.interfaces;

import br.com.camilolopes.visitor.AtualizadorConta;

/*Element: interface que define os objetos que podem

* ser atualizados por um Visitor

*

*/

public interface Atualizavel {

void atualiza(AtualizadorConta atualizadorConta);

}

Conta.java

A classe Conta implementa a Interface Atualizável. Isso, lá na frente, vai evitar o uso de if/else encadeados para verificar o tipo. Você vai ver que não temos if/else no nosso código, tudo é baseado no tipo do objeto. Muito show!!!

package br.com.camilolopes.classes;

import br.com.camilolopes.interfaces.Atualizavel;

publicabstractclass Conta implements Atualizavel {

privatedouble saldo;

public Conta(double saldo) {

this.saldo = saldo;

}

publicdouble getSaldo() {

return saldo;

}

publicvoid setSaldo(double saldo) {

this.saldo = saldo;

}

}

ContaCorrente.java

package br.com.camilolopes.classes;

import br.com.camilolopes.visitor.AtualizadorConta;

public class ContaCorrente extends Conta{

private double saldo;

public ContaCorrente(double saldo) {

super(saldo);

this.saldo = saldo;

}

public void setSaldo(double saldo) {

this.saldo = saldo;

}

public double getSaldo() {

return saldo;

}

@Override

public void atualiza(AtualizadorConta atualizadorConta) {

atualizadorConta.atualiza(this);

}

}

ContaPoupanca.java

package br.com.camilolopes.classes;

import br.com.camilolopes.visitor.AtualizadorConta;

public class ContaPoupanca extends Conta{

private double saldo;

public ContaPoupanca(double saldo) {

super(saldo);

this.saldo = saldo;

}

public void setSaldo(double saldo) {

this.saldo = saldo;

}

public double getSaldo() {

return saldo;

}

@Override

public void atualiza(AtualizadorConta atualizadorConta) {

atualizadorConta.atualiza(this);

}

}

Agora precisamos criar a classe que tem as contas, ou seja, um Banco tem N tipos de contas. Então criamos a nossa classe Banco responsável por ter as contas.

Banco.java

package br.com.camilolopes.classes;

import java.util.ArrayList;

import java.util.List;

import br.com.camilolopes.visitor.AtualizadorConta;

public class Banco {

private List<Conta> contas = new ArrayList<Conta>();

public List<Conta> getContas() {

return contas;

}

public void setContas(List<Conta> contas) {

this.contas = contas;

}

public void atualizando(AtualizadorConta atualizadorConta){

for (Conta conta :this.contas) {

/*aqui que tem a mágica

* chama a conta com base no tipo

* evitamos if/else encadeados

*/

conta.atualiza(atualizadorConta);

}

}

}

note: Observe que nossa lista é focada na classe abstract. Se amanhã surgir um novo tipo de conta, precisamos apenas informar ao Visitor o novo tipo de conta e o que ele precisa atualizar.

Pronto! Tudo já certinho. Vamos testar para ver se de fato as atualizações na coleção acontecem com base no tipo do objeto. Para isso criei uma classe com o método main:

VisitorMain.java

package br.com.camilolopes.main;

import java.util.ArrayList;

import java.util.List;

import br.com.camilolopes.classes.AtualizaConta;

import br.com.camilolopes.classes.Banco;

import br.com.camilolopes.classes.Conta;

import br.com.camilolopes.classes.ContaCorrente;

import br.com.camilolopes.classes.ContaPoupanca;

public class VisitorMain {

public static void main(String[] args) {

//lembre-se um banco tem N contas

List<Banco> lista = new ArrayList<Banco>();

//criando as contas

ContaCorrente contaCorrente = new ContaCorrente(100.00);

ContaPoupanca contaPoupanca = new ContaPoupanca(1000.00);

//criando o Banco

Banco bancoX = new Banco();

//adicionando as contas ao Banco

bancoX.getContas().add(contaPoupanca);

bancoX.getContas().add(contaCorrente);

lista.add(bancoX);

AtualizaConta atualizaConta = new AtualizaConta();

//atualizando as contas por Banco

for(Banco banco : lista){

banco.atualizando(atualizaConta);

}

//verificando atualização

for(Banco b :lista){

for(Conta c : b.getContas()){

System.out.println(c.getClass().getSimpleName() + ” ” + c.getSaldo());

}

}

}

}

Resultado

A seguir temos o resultado. Veja que os valores foram atualizados com base no cálculo:


GitHub

Os projetos Java da série estão no meu GitHub: https://github.com/camilolopes/workspacedesignpattern.git

Feito pessoal. Vou ficando por aqui… espero que vocês tenham gostado do post e da série DesignPattern.

Abracos, see ya!!

Série DesignPattern:State

Olá Pessoal,

No post de hoje vamos conhecer o design pattern chamado State. Em poucas palavras, ele é baseado no comportamento do objeto. Se o comportamento foi alterado para Y, então a forma de trabalho desse objeto é Y. Vamos ver colocando à mão na massa, acho que será mais produtivo.

Lets go…

Download dos projetos

https://github.com/camilolopes

State

É um padrão comportamental do design pattern. Este é focado em saber se o estado de um objeto foi alterado. Ou seja, o State permite alterar o comportamento de um objeto com base no estado atual.

Se o taxímetro é bandeira 1, o cálculo é feito de maneira X, com valores Y, mas se o estado atual saiu de bandeira 1 e foi para bandeira 2, o cálculo é feito de maneira  X com valor Z.

No diagrama que criei acima mostra como as classes se entendem.

Na Prática

Agora vamos conhecer praticando, e como sempre, código no modo didático para ajudar quem está vendo o assunto pela primeira vez. A seguir, nosso projeto:

Bandeira.java

Criaremos inicialmente a interface state, que é a Bandeira.

Bandeira.java

package br.com.camilolopes.interfaces.state;

public interface Bandeira {
    double calculoBandeira(double distancia);
}

As classes Bandeira 1, Bandeira2.java são classes  que implementam o State, ou seja, Bandeira 1 tem uma formula X de cálculo, a bandeira 2 também terá a forma dele calcular e assim sucessivamente.

package br.com.camilolopes.classes;
import br.com.camilolopes.interfaces.state.Bandeira;
public class Bandeira1 implements Bandeira {
    @Override
    public double calculoBandeira(double distancia) {        
        double total = distancia * 1.5 ;
        return total;
    }
}

Bandeira2.java

package br.com.camilolopes.classes;
import br.com.camilolopes.interfaces.state.Bandeira;
public class Bandeira2 implements Bandeira {
    @Override
    public double calculoBandeira(double distancia) {
        //não gosto muito desses number magic aqui, mas vou deixar por enquanto
        double total = distancia * 3.0 + 1.0;
        return total;
    }
}

Taximetro.java

package br.com.camilolopes.classes;
import br.com.camilolopes.interfaces.state.Bandeira;
/*
 * classe que mantem referencia para um State com base no estado atual
 */
public class Taximetro {
    /*um taximetro has-a bandeira
     * ou seja, para um taximetro ter vida
     * ele precisa estar associado com uma bandeira
     */
    private Bandeira bandeira;

    public Taximetro(Bandeira bandeira) {
        super();
        this.bandeira = bandeira;
    }

    public Bandeira getBandeira() {
        return bandeira;
    }

    public void setBandeira(Bandeira bandeira) {
        this.bandeira = bandeira;
    }
    //aqui o taximetro vai calcular c/ base no tipo de Bandeira
    public double calculaCorrida(double distancia){
        double totalCorrida = bandeira.calculoBandeira(distancia);
    return totalCorrida;
    }
}

Criamos o relacionamento entre o Taxímetro e a Bandeira, já que para o taxímetro existir precisa de uma bandeira.

TaximetroMain.java

import br.com.camilolopes.classes.Bandeira1;
import br.com.camilolopes.classes.Bandeira2;
import br.com.camilolopes.classes.Taximetro;

public class TaxiMain {

    public static void main(String[] args) {
        Bandeira1 bandeira1 = new Bandeira1();
        Taximetro taximetro = new Taximetro(bandeira1);
        taximetro.setBandeira(bandeira1);
        System.out.println(“Valor da corrida com bandeira 1: “+ taximetro.calculaCorrida(2.0));
        taximetro.setBandeira(new Bandeira2());
        System.out.println(“O valor da corrida com bandeira 2: ”    + taximetro.calculaCorrida(2.0));
    }
}

Feito isso, criamos uma classe main que vai nos ajudar a ver o resultado com base no tipo passado.

Resultado

A seguir temos o resultado com a Bandeira 1 e 2. Observe que a distância passada foi a mesma, porém o resultado diferente, já que cada Bandeira tem um cálculo específico e o nosso Taxímetro sabe o que mostrar com base no estado da Bandeira (1,2,3…)

E esse é o design pattern state. Vou ficando por aqui e até o próximo post.

See ya!!

Série DesignPattern: Observer

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

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!

Série DesignPattern: Decorator

Olá Pessoal,

No post de hoje vamos conhecer mais um design pattern: o Decorator. Como sempre, teremos um exemplo simples para pegarmos a ideia de onde podemos adotá-lo.

Lets go…

Decorator

Tem como objetivo adicionar funcionalidade ao objeto dinamicamente, que normalmente trata-se de uma funcionalidade opcional.

Exemplo:

Alguns modelos de carros saem de fabrica sem alguns itens, pois são considerados opcionais pelos fabricantes para os modelos XYZ. Esses opcionais são os decorators.

Vamos supor que a Volks vai adicionar um item na Fabricação de um novo carro, ou seja, uma nova funcionalidade será adicionada ao sistema de fabricação daquele modelo específico. Então essa funcionalidade será implementada por um novo objeto: decorator, mas queremos aproveitar o que já existe no modelo atual, ou seja, não quero trocar todo o meu sistema de produção somente para adicionar neon aos faróis, mas quero comprar um equipamento que possa adicionar ao meu sistema de produção atual e dizer ao sistema o seguinte: “se o carro que está na esteira é do tipo new fox, o farol será de neon, caso seja do tipo fox, será o farol normal”.

O decorator

O decorator é uma classe abstract que implementa a mesma interface do modelo atual. As classes concretas vão extends abstract Decorator que terá a nova funcionalidade. Na prática, eu posso dizer que o novo modelo de carro chamado “New Fox” vai extends abstract Decorator. Lembre-se que a nova funcionalidade só é chamada quando o novo tipo é invocado na construção/criação do objeto.

No dia-dia

É muito comum isso acontecer depois de certo tempo que a aplicação já está em produção. Os motivos são vários: mudanças nas regras de negócios, necessidade específica do usuário etc. Um caso bem comum é futuramente o usuário querer um novo tipo de relatório com informações que apenas o user do tipo administrador pode ter acesso. Nessa funcionalidade podemos usar o Decorator para ter as novas informações que não constam nos relatórios já existentes.  Veja no diagrama a seguir como seria um cenário com o Decorator.

Desenvolvendo

Chegou a hora de colocarmos a mão na massa com decorator. A seguir temos o projeto que criei para vermos o decorator em ação. Como sempre, adicionei comentários in line com o objetivo de deixar o código mais didático.

Interface

A seguir temos a interface que fabrica os faróis:

package br.com.camilolopes.interfaces;

public interface Fabrica {

                void farol(String mensagem);

}

Fox.java

É uma classe que representa um tipo de carro que tem os faróis de um determinado tipo:

package br.com.camilolopes.classes;

 import br.com.camilolopes.interfaces.Fabrica;

 public class Fox implements Fabrica {

                @Override

               public void farol(String mensagem) {

                               System.out.println(“adicionando farois comuns ao ” + mensagem);           

                }

}

NewFarol.java

É a classe decorator que implementa a mesma interface que os carros comuns já implementam para os faróis.

package br.com.camilolopes.decorator;

import br.com.camilolopes.interfaces.Fabrica;

/*

 * aqui é o nosso decorator

 */

public abstract class NewFarol implements Fabrica {

                @Override

                public  abstract void farol(String mensagem);        

}

NewFox.java

É uma classe que representa o novo tipo de carro que vai possuir os novos faróis.

package br.com.camilolopes.decorator;

/*

 * classe que vai ter a nova funcionalidade implementada

 * conhecida como: ConcreteDecorator

 */

public class NewFox extends NewFarol {

                @Override

                public void farol(String mensagem) {

                               System.out.println(“Adicionando Farol de Neon”);

                               System.out.println(this.farolNeon() + ” ao ” + mensagem);

                }

                //nova funcionalidade sendo adicionado ao farol

                public String farolNeon() {

                               return “Farol de neon adicionado com sucesso”;

                }

}

FabricaMain.java

Essa é a classe que vai fabricando os carros com  base no tipo ela adiciona as funcionalidades corretamente. Como podemos ver, quando o tipo do carro for NewFox os faróis adicionados serão diferentes do modelo Fox.

 package br.com.camilolopes.main;

import br.com.camilolopes.classes.Fox;

import br.com.camilolopes.decorator.NewFox;

import br.com.camilolopes.interfaces.Fabrica;

public class FabricaMain {

            public static void main(String[] args) {

                        // chegou na esteira o modelo newFox

                        Fabrica fabrica1 = new NewFox();

                        fabrica1.farol(“New Fox”);

                        //chegou na esteira o modelo fox

                        Fabrica fabrica2 = new Fox();

                        fabrica2.farol(“Fox”);

            }

}

Rode sua aplicação para ver o resultado

Resultado

A seguir, o resultado no console:

Vou ficando por aqui, esse foi o design pattern Decorator. Espero que tenham curtido o post de hoje. Até o próximo post.

Abracos, see ya!