O padrão de desenho mais correcto a aplicar neste caso é o Observer. A entidade ConcreteSubject deste padrão corresponderá à entidade Emprestimo do exemplo de aplicação. A entidade Subject fornece a funcionalidade genérica de notificar todas entidades interessadas sempre que o subject é alterada:
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer ob : observers) {
ob.update(this);
}
}
}
Nesta concretização do padrão, a notificação envia a referência do objecto que foi alterado, por forma a que cada observer que é notificado recebe a referência do objecto alterado (se bem que possa necessitar depois de realizar um downcast para a classe concreta).
A classe Emprestimo necessita de ser alterada por forma a notificar todos as entidades interessadas sempre que a taxa de juro é alterada:
public class Emprestimo extends Subject {
// ...
public void alteraJuro(float juro) {
_juro = juro;
notifyObservers();
}
//...
}
De acordo com a estrutura do padrão, as entidades que estejam interessados em receber uma notificação sempre que as condições de um empréstimo são alteradas são representadas pela entidade abstracta Observer:
interface Observer {
void update(Subject subject);
}
Cada diferente tipo de observer que exista necessita de concretizar a interface Obeserver, especificando o método update com o comportamento correcto para a entidade em causa. Por exemplo, supondo que a classe Jornal de Economia apenas quer imprimir o novo valor do juro, o código desta classe seria o seguinte:
public class JornalEconomia implements Observer {
public void update(Subject sub) {
System.out.println("Novo juro: " + ((Emprestimo)sub).obtemJuro());
}
}