Observer

Intenção

Definir uma dependência um-para-muitos entre objetos, de maneira que quando um objeto muda de estado todos os seus dependentes são notificados e atualizados automaticamente.

Vantagens

Desvantagens

Exemplos

Exemplo #1

Uma entidade de pagamento pode receber boletos dos bancos A e B. Ao efetuar o pagamento a entidade precisa comunicar ao Banco correspondente o recebimento do mesmo. É possível efetuar essa comunicação a partir da notificação dos objetos que monitoram o estado dos objetos do tipo boleto, assim o uso do padrão Observer permite que sempre que um boleto do Banco A for pago o mesmo será notificado, da mesma forma quando um boleto do Banco B for pago, o Banco B será notificado. No exemplo abaixo, essa notificação é feita ao objeto observador dos boletos do Banco A(BankAObserver),para boletos do Banco A pagos, e ao objeto observador do Banco B(BankBObserver), para boletos do Banco B pagos.

Diagrama de Classe

Exemplo #1 - Diagrama

Participantes

  • Subject(Subject): conhece os seus observadores. Um número qualquer de objetos Observer pode observar um subject. Fornece uma interface para acrescentar e remover objetos, permitindo associar e desassociar observer.
  • Observer(Observer): define uma interface de atualização para objetos que deveriam ser notificados sobre mudanças em um Subject.
  • ConcreteSubject(BankSlipSubject): armazena estados de interesse para objetos ConcreteObserver. Envia uma notificação para os seus observadores quando seu estado muda.
  • ConcreteObserver(BankAObserver, BankBObserver): mantém uma referência para um objeto ConcreteSubject. Armazena estados que deveriam permanecer consistentes com os do Subject. Implementa a interface de atualização de Observer, para manter seu estado consistente com o do subject.

Código

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package observerbriof;

/**
 *
 * @author patrickbelem
 */
public class BankAObserver implements Observer {
    
 private Subject bankSlipSubject;
    
    public BankAObserver(Subject bankSlipSubject) { 
        this.bankSlipSubject = bankSlipSubject;
        bankSlipSubject.attach(this);
    }    
    
  @Override
  public void update(BankSlip bankSlip) {
      System.out.println("BANK SLIPS FROM BANK A PAID AND NOTIFIED:\nBank Slip:"+ bankSlip.getCode() +"\nShop:"+ bankSlip.getShopName()+
                               "\nAmount Received:"+ bankSlip.getValue()+ "\nBank Code:"+ bankSlip.getBankCode() +"\nCurrent Status:"+ bankSlip.getStatus());
      System.out.println("========================");
     
  }
   
}
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package observerbriof;

/**
 *
 * @author patrickbelem
 */
public class BankBObserver implements Observer{
    
  private Subject bankSlipSubject;
      
    public BankBObserver(Subject bankSlipSubject) { 
        this.bankSlipSubject = bankSlipSubject;
        bankSlipSubject.attach(this);
    }    
    
  @Override
  public void update(BankSlip bankSlip) {
       System.out.println("BANK SLIPS FROM BANK B PAID AND NOTIFIED:\nBank Slip:"+ bankSlip.getCode() +"\nShop:"+ bankSlip.getShopName()+
                               "\nAmount Received:"+ bankSlip.getValue()+ "\nBank Code:"+ bankSlip.getBankCode() +"\nCurrent Status:"+ bankSlip.getStatus());
       System.out.println("========================");
        
   }
      
}
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package observerbriof;

/**
 *
 * @author patrickbelem
 */
public class BankSlip {
    
    protected int    code;
    protected String shopName;
    protected double value;
    protected int bankCode;
    protected String status;

  
    public BankSlip(int code, String shopName, int bankCode, double value, String status) {
        this.code = code;
        this.shopName = shopName;
        this.bankCode = bankCode;
        this.value = value;
        this.status = status;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public void setShopName(String shopName) {
        this.shopName = shopName;
    }
    public void setBankCode(int bankCode) {
        this.bankCode = bankCode;
    }
    public void setValue(double value) {
        this.value = value;
    }
    public void setStatus(String status) {
        this.status = status;
    }
     public int getCode() {
        return code;
    }
    public String getShopName() {
        return shopName;
    }
    
    public int getBankCode() {
       return bankCode;
    }

    public double getValue() {
        return value;
    }

    public String getStatus() {
        return status;
    }

}
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package observerbriof;

import java.util.ArrayList;

/**
 *
 * @author patrickbelem
 */
public class BankSlipSubject implements Subject{
       
    private ArrayList observers;
    protected BankSlip bankSlip;
    
    public BankSlipSubject() {
        observers = new ArrayList();
    }
    
   public void setState(BankSlip bankSlip) { //setMeasurements
       this.bankSlip = bankSlip;
       notifyObservers();
    }
     
    @Override
    public void attach(Observer observer) {
        observers.add(observer);
    }
    
    @Override
     public void detach(Observer observer) {
       int i = observers.indexOf(observer);
		if (i >= 0) {
			observers.remove(i);
		}
    }
    @Override
       public void notifyObservers() {
       for (int i = 0; i < observers.size(); i++) {
			Observer observer = (Observer)observers.get(i);
			observer.update(bankSlip);
                        
		}
    }

    
}
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package observerbriof;

/**
 *
 * @author patrickbelem
 */
public class Client {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
     
        
        //WeatherData weatherData = new WeatherData();
        BankSlipSubject bankSlipSubject1 = new BankSlipSubject();
        BankSlipSubject bankSlipSubject2 = new BankSlipSubject();
        
	
        BankAObserver baObserver = new BankAObserver(bankSlipSubject1);
        BankBObserver bbObserver = new BankBObserver(bankSlipSubject2);
        
        BankSlip bankSlip1 = new BankSlip(2520,"Casas Bahia", 1, 1000,"Not Paid"); 
        BankSlip bankSlip2 = new BankSlip(3250,"Eletrocenter", 2, 2000,"Not Paid"); 
        BankSlip bankSlip3 = new BankSlip(2350,"Americanas", 1, 3450,"Not Paid"); 
        BankSlip bankSlip4 = new BankSlip(5050,"Ricardo Eletro", 2, 1250,"Not Paid"); 
        BankSlip bankSlip5 = new BankSlip(6050,"Magazine Luiza", 1, 1520,"Not Paid"); 
        BankSlip bankSlip6 = new BankSlip(1550,"Shoptime", 2, 3652,"Not Paid"); 
        
        PaymentEntity ep1 = new PaymentEntity("Bank X", "Bank");
        PaymentEntity ep2 = new PaymentEntity("Loteria cavaleiros", "Lottery");
        
                        
        ep1.makePayment(bankSlip1,bankSlipSubject1);  
        ep1.makePayment(bankSlip2,bankSlipSubject2);
        ep1.makePayment(bankSlip3,bankSlipSubject1);
        ep2.makePayment(bankSlip4,bankSlipSubject2);
        ep1.makePayment(bankSlip5,bankSlipSubject1);
        ep2.makePayment(bankSlip6,bankSlipSubject2);
        
        
        
        
        
    }
    
}
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package observerbriof;

/**
 *
 * @author patrickbelem
 */
public interface Observer {
    
    public void update(BankSlip bankSlip);

    
}
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package observerbriof;

/**
 *
 * @author patrickbelem
 */
public class PaymentEntity {

     protected String name;
     protected String type;

       
    public PaymentEntity(String name, String type) {
        this.name = name;
        this.type = type;
    }
    
    public void setType(String type) {
        this.type = type;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public String getType() {
        return type;
    }

    
    public void makePayment(BankSlip bankSlip, BankSlipSubject bankSlipSubject){
          bankSlip.setStatus("Paid"); 
          bankSlipSubject.setState(bankSlip); 
        
    }
    
}
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package observerbriof;


/**
 *
 * @author patrickbelem
 */
public interface Subject {
   
    public void attach(Observer observer);

    public void detach(Observer observer);
    
    public void notifyObservers();

}
Clique aqui para fazer o download do código completo de implementação deste Design Pattern.

Padrões Relacionados

Este Padrão pode ser usado para resolver os seguintes problemas: