Factory Method

Origem: Wikipédia, a enciclopédia livre.
Ir para: navegação, pesquisa

Factory Method, na ciência da computação, é um padrão de projeto de software (design pattern, em inglês) que permite as classes delegar para subclasses decidirem. O factory method permite delegar a instanciação para as subclasses.

Estrutura[editar | editar código-fonte]

Diagrama UML da estrutura do padrão Factory Method

O padrão Factory Method, da forma como foi descrito no livro Design Patterns: Elements of Reusable Object-Oriented Software, contém os seguintes elementos:

  • Creator — declara o factory method (método de fabricação) que retorna o objeto da classe Product (produto). Este elemento também pode definir uma implementação básica que retorna um objeto de uma classe ConcreteProduct (produto concreto) básica;
  • ConcreteCreator — sobrescreve o factory method e retorna um objeto da classe ConcreteProduct;
  • Product — define uma interface para os objectos criados pelo factory method;
  • ConcreteProduct — uma implementação para a interface Product.

Utilização[editar | editar código-fonte]

Este padrão é muito utilizado em frameworks para definir e manter relacionamentos entre objetos. O framework Spring, dependendo da configuração, pode utilizar um Factory Method para criar os seus beans.[1]

Este padrão pode ser utilizado na construção de um framework que suporta aplicações que apresentam múltiplos documentos ao usuário. Normalmente este tipo de aplicação manipula um número variável de formatos de documento e, por isso, este framework deve ser flexível o bastante para suportar qualquer formato. Uma solução para este problema poderia disponibilizar, no framework, o código para alguns dos formatos mais utilizados. Mas, na prática, esta solução seria uma implementação pouco flexível, e até mesmo incompleta, já que é custoso implementar os mais variados formatos. O padrão Factory Method propõe uma solução que deixa para o cliente (a implementação da aplicação) a tarefa de suportar os formatos necessários e para o framework o papel de definição de uma abstração que oferece uma interface única para criação de documentos.

Este framework seria baseado em duas classes abstratas, que representam a Aplicação e o Documento. O cliente do framework fornece um par de classes concretas, uma aplicação e o respectivo documento, para cada um dos formatos de Documento suportados pela Aplicação. Se for necessário apresentar um documento que suporte desenho, por exemplo, o cliente deve disponibilizar as classes AplicacaoDesenho e DocumentoDesenho (supondo que o sufixo "Desenho" indique classes que suportam esta funcionalidade).

O objetivo do Factory Method está em diversas classes que implementam a mesma operação, retornarem o mesmo tipo abstrato, mas internamente instanciam diferentes classes que o implementam. Com o Factory Method o criador do objeto faz uma escolha de qual classe instanciar para o cliente. Para ser um Factory Method o método precisa retornar uma interface ou uma classe abstrata e, dependendo das necessidades do cliente, criar um objeto determinado como retorno. Um exemplo clássico do Factory Method são os iteradores tanto em Java como em .NET.

Exemplo[editar | editar código-fonte]

Neste exemplo, uma aplicação, que é construída através de um framework baseado no padrão Factory Method, suporta a criação de documentos do tipo MeuDocumento. O framework é constituído pelas classes abstratas Aplicacao e Documento. A aplicação disponibiliza as classes concretas MinhaAplicacao e MeuDocumento. A classe MinhaAplicacao é uma implementação da abstração definida pela classe Aplicacao.

Diagrama[editar | editar código-fonte]

Exemplo de Diagrama em UML para o Padrão Factory Method.

A chave deste padrão está na declaração do método abstrato criaDocumento, da classe Aplicacao, e na sua utilização pelo método novoDocumento. Este arranjo permite que o método novoDocumento crie documentos sem conhecer os detalhes de implementação, existentes em cada tipo de documento suportado pela aplicação. Isto permite que a implementação do método criaDocumento (neste exemplo situada na classe MinhaAplicacao) varie livremente, para atender os diversos formatos possivelmente suportados, sem que seja necessário modificar o código das classes abstratas.

Código em Java[editar | editar código-fonte]

Este código, escrito na linguagem Java, demonstra a implementação do diagrama mostrado acima.

 
/**
* Abstração de uma Aplicação capaz de manipular
* documentos.
*/
 abstract class Aplicacao {
 
      protected Documento doc;
 
      /**
      * Abstração do Factory Method
      */
       abstract Documento criaDocumento();
 
       void novoDocumento() {
           this.doc = this.criaDocumento();
       }
 
       void abrirDocumento() {
           this.doc.abrir();
       }
  }
 
/**
* Abstração de um Documento.
*/
  abstract class Documento {
 
      void abrir() {
          System.out.println("Documento:Abrir documento!");
      }
 
      void fechar() {
          System.out.println("Documento:Fechar documento!");
      }
 
      void gravar() {
          System.out.println("Documento:Gravar documento!");
      }
  }
 
/**
* Esta classe concreta contém a implementação
* de uma aplicação capaz de manipular documentos
* do tipo MeuDocumento.
*/
  class MinhaAplicacao extends Aplicacao {
 
 	/**
 	 * Uma implementação do Factory Method. Este método é 
 	 * especializado na criação de documentos do tipo MeuDocumento
 	 */
 	Documento criaDocumento() {
            return new MeuDocumento();
 	}
  }
 
/**
* Esta classe concreta contém a implementação
* de um tipo de documento específico.
* /
  class MeuDocumento extends Documento {
 
  }

Código em VB.NET[editar | editar código-fonte]

O mesmo exemplo acima, em linguagem Visual Basic .NET.

Public MustInherit Class Aplicacao
 
    Private doc As Documento
 
    MustOverride Function criaDocumento() As Documento
 
    Sub novoDocumento()
        Me.doc = Me.criaDocumento
    End Sub
 
    Sub abrirDocumento()
        Me.doc.abrir()
    End Sub
 
End Class
 
Public MustInherit Class Documento
 
    Sub abrir()
        Console.WriteLine("Documento:Abrir documento!")
    End Sub
 
    Sub fechar()
        Console.WriteLine("Documento:Fechar documento!")
    End Sub
 
    Sub gravar()
        Console.WriteLine("Documento:Gravar documento!")
    End Sub
 
End Class
 
Public Class MinhaAplicacao
    Inherits Aplicacao
 
    Public Overrides Function criaDocumento() As Documento
 
        Return New MeuDocumento
 
    End Function
End Class
 
Public Class MeuDocumento
    Inherits Documento
 
End Class

Código em C#[editar | editar código-fonte]

O mesmo exemplo acima, em linguagem C#.

public abstract class Aplicacao
{
    private Documento doc;
 
    Documento criaDocumento();
 
    void novoDocumento()
    {
        this.doc = this.criaDocumento();
    }
 
 
    void abrirDocumento()
    {
        this.doc.abrir();
    }
 
}
 
public abstract class Documento
{
    void abrir()
    {
        Console.WriteLine("Documento:Abrir documento!");
    }
 
    void fechar()
    {
        Console.WriteLine("Documento:Fechar documento!");
    }
 
    void gravar()
    {
        Console.WriteLine("Documento:Gravar documento!");
    }
}
 
public class MinhaAplicacao : Aplicacao
{
    public Documento criaDocumento()
    {
        return new MeuDocumento();
    }
}
 
public class MeuDocumento : Documento
{
 
}

Padrões relacionados[editar | editar código-fonte]

Referências

  1. Rod Johnson, Juergen Hoeller, Alef Arendsen, Colin Sampaleanu, Rob Harrop, Thomas Risberg, Darren Davison, Dmitriy Kopylenko, Mark Pollack, Thierry Templier, Erwin Vervaet, Portia Tung, Ben Hale, Adrian Colyer, John Lewis, Costin Leau, Rick Evans. The Spring Framework - Reference Documentation (em Inglês). Visitado em 16 de maio de 2007.

Bibliografia[editar | editar código-fonte]