Factory Method

Intenção

Definir uma interface para criar um objeto, mas deixar as subclasses decidirem que classe instanciar. O Factory Method permite adiar a instanciação para subclasse.

Vantagens

Desvantagens

Exemplos

Exemplo #1

Um sistema de software deve ser desenvolvido para controlar um conjunto de diferentes tipos de carros, cada um de uma determinada montadora. Para exemplificar suponha os 2 seguintes modelos/montadoras:
 
Palio – Fiat
Gol – Volkswagen
 
Sempre que for necessário criar um carro Palio, por exemplo, a fábrica Fiat deverá ser acionada, da mesma forma, quando um carro Gol precisar ser criado, a fábrica volkswagem deverá ser acionada. Podemos observar que precisamos de uma fábrica para cada tipo de carro, assim o uso do padrão Factory Method permite que tais objetos sejam criados a partir de uma interface, deixando que as subclasses decidam que classe instanciar. Isso é feito a partir de um método fábrica implementado de forma polimórfica. No exemplo abaixo as classes FiatConcreteCreator e VolksConcreteCreator reescrevem o método fábrica herdado de CarCreator.

Diagrama de Classe

Exemplo #1 - Diagrama

Participantes

  • Product(Car): Define a interface de objetos que o método fábrica cria.
  • ConcreteProduct(ConcreteProductGol, ConcreteProductPalio): implementa a interface de Product.
  • Creator(CarCreator): Declara o método fábrica, o qual retorna um objeto do tipo Product. Creator pode também definir uma implementação por omissão do método factory que retorna por omissão um objeto ConcreteProduct. Pode chamar o método factory para criar um objeto Product.
  • ConcreteCreator(VolksConcreteCreator, FiatConcreteCreator): Redefine o método-fábrica para retornar a uma instância de um ConcreteProduct.

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 factorymethod2;

/**
 *
 * @author patrick
 */
public abstract class Car {
    
    private String model;     
    private String factory;     
    private String category;    
    
    
  public void showInformation() {
              
        System.out.println("Model:" + this.getModel()+ " \nFactory:" + this.getFactory() +  "\nCategory: " + this.getCategory());

    }
    
    public String getModel() {
       return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getFactory() {
        return factory;
    }

    public void setFactory(String factory) {
        this.factory = factory;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

   
}
/*
 * 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 factorymethod2;

/**
 *
 * @author patrick
 */
public abstract class CarCreator {
    
    public void buildCar() 
	{
		Car carro = factoryMethod();
	}
	
	protected abstract Car factoryMethod();
    
    
}
/*
 * 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 factorymethod2;

import javax.swing.JOptionPane;

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

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
                       
                    CarCreator creator1 = new FiatConcreteCreator();              
                    creator1.buildCar();
                    
                    CarCreator creator2 = new VolksConcreteCreator();              
                    creator2.buildCar();
                
        
    }
    
}
/*
 * 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 factorymethod2;

/**
 *
 * @author patrick
 */
public class ConcreteProductGol extends Car{

public ConcreteProductGol(){
     
        this.setModel("Gol");
        this.setFactory("Volks");
        this.setCategory("Hatch");
        this.showInformation();
      
  }    
    
}
/*
 * 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 factorymethod2;

/**
 *
 * @author patrick
 */
public class ConcreteProductPalio extends Car{
    
public ConcreteProductPalio(){
       
        this.setModel("Palio");
        this.setFactory("Fiat");
        this.setCategory("Hatch");
        this.showInformation();
   
}

}
/*
 * 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 factorymethod2;

/**
 *
 * @author patrick
 */
public class FiatConcreteCreator extends CarCreator{
    

protected Car factoryMethod(){
           
    return new ConcreteProductPalio();
                 
        }
}
/*
 * 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 factorymethod2;

/**
 *
 * @author patrick
 */
public class VolksConcreteCreator extends CarCreator{
    

protected Car factoryMethod(){
           
        return new ConcreteProductGol();
                 
        }
}
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: