Análise e Projeto Orientados  
por Objetos  
Aula 08 – Padrões GoF (Observer e Builder)  
Edirlei Soares de Lima  
<edirlei@iprj.uerj.br>  
Padrões GoF  
•
Criação:  
•
Estruturais:  
• Comportamentais:  
–
–
–
–
–
Abstract Factory  
Builder  
Factory Method  
Prototype  
Singleton  
–
–
–
–
–
–
–
Adapter  
Bridge  
– Chain of Responsibility  
– Command  
– Interpreter  
– Iterator  
– Mediator  
– Memento  
Composite  
Decorator  
Façade  
Flyweight  
Proxy  
– Observer  
–
–
–
–
State  
Strategy  
Template Method  
Visitor  
Observer  
•
•
Existem situações onde diversos objetos mudam seu estado de acordo  
com a mudança de estado de outro objeto.  
Define uma relação de dependência 1:N entre objetos, de tal forma que,  
quando um objeto (assunto) tem seu estado modificado, os seus objetos  
dependentes (observadores) são notificados.  
Observer  
Observer – Exemplo  
Observer – Implementação  
public class Subject  
{
private List<Observer> observers = new ArrayList<Observer>();  
private int state;  
public int getState(){  
return state;  
}
public void setState(int state){  
this.state = state;  
notifyAllObservers();  
}
public void attach(Observer observer){  
observers.add(observer);  
}
public void notifyAllObservers(){  
for (Observer observer : observers){  
observer.update();  
}
}
}
Observer – Implementação  
public abstract class Observer  
{
protected Subject subject;  
public abstract void update();  
}
public class BinaryObserver extends Observer  
{
public BinaryObserver(Subject subject)  
{
this.subject = subject;  
this.subject.attach(this);  
}
@Override  
public void update()  
{
System.out.println("Binary String: " +  
Integer.toBinaryString(subject.getState()));  
}
}
Observer – Implementação  
public class OctalObserver extends Observer  
{
public OctalObserver(Subject subject)  
{
this.subject = subject;  
this.subject.attach(this);  
}
@Override  
public void update()  
{
System.out.println("Octal String: " +  
Integer.toOctalString( subject.getState()));  
}
}
Observer – Implementação  
public class HexaObserver extends Observer  
{
public HexaObserver(Subject subject)  
{
this.subject = subject;  
this.subject.attach(this);  
}
@Override  
public void update()  
{
System.out.println("Hex String: " + Integer.toHexString(  
subject.getState()).toUpperCase());  
}
}
Observer – Implementação  
public static void main(String[] args)  
{
Subject subject = new Subject();  
Observer ho = new HexaObserver(subject);  
Observer ob = new OctalObserver(subject);  
Observer bo = new BinaryObserver(subject);  
System.out.println("First state change: 15");  
subject.setState(15);  
System.out.println("Second state change: 10");  
subject.setState(10);  
}
Observer – Aplicabilidade  
•
•
•
Quando uma mudança em um objeto requer uma mudança  
em outros, e não se sabe como esses outros objetos  
efetivamente fazem suas mudanças;  
Quando um objeto deve poder notificar outros objetos sem  
assumir nada sobre eles. Dessa forma evita-se que os objetos  
envolvidos fiquem fortemente acoplados;  
Possibilita baixo acoplamento entre os objetos dependentes  
(os observadores) e o assunto.  
Builder  
•
•
Intenção: separar a construção de objetos complexos da sua  
representação, de modo que o mesmo processo de  
construção possa criar diferentes representações.  
A classe Builder constroi os objetos complexos passo a passo.  
Builder  
Builder – Exemplo  
Builder – Implementação  
public interface Item  
{
public String name();  
public Packing packing();  
public float price();  
}
public interface Packing  
{
public String pack();  
}
Builder – Implementação  
public class Wrapper implements Packing  
{
@Override  
public String pack()  
{
return "Wrapper";  
}
}
public class Bottle implements Packing  
{
@Override  
public String pack()  
{
return "Bottle";  
}
}
Builder – Implementação  
public abstract class Burger implements Item {  
@Override  
public Packing packing() {  
return new Wrapper();  
}
@Override  
public abstract float price();  
}
public abstract class ColdDrink implements Item {  
Override  
@
public Packing packing() {  
return new Bottle();  
}
@Override  
public abstract float price();  
}
Builder – Implementação  
public class VegBurger extends Burger {  
Override  
@
public float price() {  
return 25.0f;  
}
@Override  
public String name() {  
return "Veg Burger";  
}
}
public class ChickenBurger extends Burger {  
Override  
@
public float price() {  
return 50.5f;  
}
@Override  
public String name() {  
return "Chicken Burger";  
}
}
Builder – Implementação  
public class Coke extends ColdDrink {  
Override  
@
public float price() {  
return 30.0f;  
}
@Override  
public String name() {  
return "Coke";  
}
}
public class Pepsi extends ColdDrink {  
Override  
@
public float price() {  
return 35.0f;  
}
@Override  
public String name() {  
return "Pepsi";  
}
}
Builder – Implementação  
public class Meal {  
private List<Item> items = new ArrayList<Item>();  
public void addItem(Item item){  
items.add(item);  
}
public float getCost(){  
float cost = 0.0f;  
for (Item item : items) {  
cost += item.price();  
}
return cost;  
}
public void showItems(){  
for (Item item : items) {  
System.out.print("Item : " + item.name());  
System.out.print(", Packing : " + item.packing().pack());  
System.out.println(", Price : " + item.price());  
}
}
}
Builder – Implementação  
public class MealBuilder {  
public Meal prepareVegMeal()  
{
Meal meal = new Meal();  
meal.addItem(new VegBurger());  
meal.addItem(new Coke());  
return meal;  
}
public Meal prepareNonVegMeal()  
{
Meal meal = new Meal();  
meal.addItem(new ChickenBurger());  
meal.addItem(new Pepsi());  
return meal;  
}
}
Builder – Implementação  
public static void main(String[] args)  
{
MealBuilder mealBuilder = new MealBuilder();  
Meal vegMeal = mealBuilder.prepareVegMeal();  
System.out.println("Veg Meal");  
vegMeal.showItems();  
System.out.println("Total Cost: " + vegMeal.getCost());  
Meal nonVegMeal = mealBuilder.prepareNonVegMeal();  
System.out.println("\n\nNon-Veg Meal");  
nonVegMeal.showItems();  
System.out.println("Total Cost: " + nonVegMeal.getCost());  
}
Builder vs Abstract Factory  
•
•
O padrão Builder é muitas vezes comparado com o padrão  
Abstract Factory pois ambos podem ser utilizados para a  
construção de objetos complexos.  
A principal diferença entre eles é que o Builder constrói  
objetos complexos passo a passo e o Abstract Factory constrói  
famílias de objetos, simples ou complexos, de uma só vez.