O padrão AbstractFactory

23/02/2010 | Por Carlos Eduardo Ferreira | Categoria: PADRÕES DE PROJETO

O padrão Abstract Factory

Abstract Factory é um padrão de criação e como o nome diz ‘Fabrica Abstrata’ este padrão é utilizado para a criação de objetos relacionados ou ‘família de objetos’.

Figura 1: Diagrama de Classes para o Abstract Factory.

Figura 1: Diagrama de Classes para o Abstract Factory.

Problema

Precisamos criar famílias de objetos relacionados e cada objeto de cada família tem sua implementação especifica. Você precisa garantir que dada uma situação você escolherá a família correta de objetos que será utilizado sem misturar os objetos de famílias diferentes.

Imagine que você esteja desenvolvendo uma aplicação de gerenciamento de documentos (GED) e precise tratar diferentes tipos de arquivos: txt, pdf, doc e etc.

Dentro deste contexto você terá objetos para extração e indexação de conteúdo para cada tipo de arquivo (mime-type).

Figura 2: Diagrama de Classes para o Abstract Factory.

Figura 2: Diagrama de Classes para o Abstract Factory do nosso exemplo.

Implementação

Observe que na classe Client utiliza somente as interfaces não as implementações.

package br.ged.abstractfactory.interfaces;
 
public interface DocumentFactory 
{
	public static final String TXT = "TXT";
 
	public static final String PDF = "PDF";
 
	public DocumentReader createDocumentReader( );
 
	public DocumentWriter createDocumentWriter( );
 
}
package br.ged.abstractfactory.interfaces;
 
import java.io.OutputStream;
 
public interface DocumentReader {
 
	public OutputStream readeFile( String file );
 
}
package br.ged.abstractfactory.interfaces;
 
import java.io.InputStream;
 
public interface DocumentWriter {
 
	public void writeFile( InputStream inputStream );
 
}
package br.ged.abstractfactory.concrete;
 
import br.ged.abstractfactory.interfaces.DocumentFactory;
import br.ged.abstractfactory.interfaces.DocumentReader;
import br.ged.abstractfactory.interfaces.DocumentWriter;
 
public class PdfDocumentFactory implements DocumentFactory 
{
 
	@Override
	public DocumentReader createDocumentReader( ) 
	{
		System.out.println( "PdfDocumentFactory.createDocumentReader ::: PDF" );
		return new PdfDocumentReader( );
	}
 
	@Override
	public DocumentWriter createDocumentWriter( ) 
	{
		System.out.println( "PdfDocumentFactory.createDocumentWriter ::: PDF" );
		return new PdfDocumentWriter( );
	}
 
}
package br.ged.abstractfactory.concrete;
 
import java.io.OutputStream;
 
import br.ged.abstractfactory.interfaces.DocumentReader;
 
public class PdfDocumentReader implements DocumentReader {
 
	@Override
	public OutputStream readeFile( String file ) {
		System.out.println( "PdfDocumentReader.readeFile ::: PDF" );
		return null;
	}
 
}
package br.ged.abstractfactory.concrete;
 
import java.io.InputStream;
 
import br.ged.abstractfactory.interfaces.DocumentWriter;
 
public class PdfDocumentWriter implements DocumentWriter {
 
	@Override
	public void writeFile(InputStream inputStream) {
		System.out.println( "PdfDocumentWriter.writeFile ::: PDF" );
	}
 
}
package br.ged.abstractfactory.concrete;
 
import br.ged.abstractfactory.interfaces.DocumentFactory;
import br.ged.abstractfactory.interfaces.DocumentReader;
import br.ged.abstractfactory.interfaces.DocumentWriter;
 
public class TxtDocumentFactory implements DocumentFactory 
{
 
	@Override
	public DocumentReader createDocumentReader( ) 
	{
		System.out.println( "TxtDocumentFactory.createDocumentReader ::: TXT" );
		return new TxtDocumentReader( );
	}
 
	@Override
	public DocumentWriter createDocumentWriter( ) 
	{
		System.out.println( "TxtDocumentFactory.createDocumentWriter ::: TXT" );
 
		return new TxtDocumentWriter( );
	}
 
}
package br.ged.abstractfactory.concrete;
 
import java.io.OutputStream;
 
import br.ged.abstractfactory.interfaces.DocumentReader;
 
public class TxtDocumentReader implements DocumentReader {
 
	@Override
	public OutputStream readeFile(String file) {
		System.out.println( "TxtDocumentReader.readeFile ::: TXT" );
		return null;
	}
}
package br.ged.abstractfactory.concrete;
 
import java.io.InputStream;
 
import br.ged.abstractfactory.interfaces.DocumentWriter;
 
public class TxtDocumentWriter implements DocumentWriter {
 
	@Override
	public void writeFile(InputStream inputStream) {
		// persiste arquivo baseado no inputstream
		System.out.println( "TxtDocumentWriter.writeFile ::: TXT" );
	}
 
}
package br.ged.abstractfactory.concrete;
 
import java.io.OutputStream;
 
import br.ged.abstractfactory.interfaces.DocumentFactory;
import br.ged.abstractfactory.interfaces.DocumentReader;
import br.ged.abstractfactory.interfaces.DocumentWriter;
 
public class Client 
{
    public static void main(String[] args) throws Exception
    {
    	// OBSERVE QUE USAMOS AQUI APENAS AS INTEFACES
	    DocumentFactory documentFactory =  createDocumentFactory( "PDF" );
 
	    DocumentWriter documentWriter = documentFactory.createDocumentWriter();
	    documentWriter.writeFile( null );
 
	    DocumentReader documentReader = documentFactory.createDocumentReader();
	    OutputStream outputStream = documentReader.readeFile("dados.txt");
 
	}
 
    public static DocumentFactory createDocumentFactory( String type ) 
    {
    	if ( type.equalsIgnoreCase( DocumentFactory.PDF ) )
    		return new PdfDocumentFactory();
    	if( type.equalsIgnoreCase( DocumentFactory.TXT ) )
    		return new TxtDocumentFactory();
 
    	return null;
    }
}

Utilizações comuns

Utilize quando quiser ter independência de como seus objetos são criados, ou seja você deseja desacoplar sua aplicação e as famílias de objetos utilizadas por ela. Dessa forma podemos trocar a família de objetos utilizadas na aplicação sem afetar o código fonte.

Utilize quando quiser fornecer uma biblioteca de classes de produtos e quer revelar somente suas interfaces e as implementações.

Conclusões

Embora utilizar o AbstractFactory gere um trabalho adicional (escrever produtos abstratos, fabricas abstratas, e suas respectivas implementações) , utilizar fabricas é uma boa prática de programação e ajuda a reduzir o acoplamento e conseqüentemente melhora manutenção do sistema.

Tags: , ,

Deixar comentário