• Skip to primary navigation
  • Skip to content

Mauda

IT, Java and Music

Graduação   SCJP   Mestrado
  • Apresentação
  • Certificação Java
  • JPA
    • Exceptions
  • JSF
  • Versionamento
  • Contato

Design Patterns – Factory

July 13, 2015 by Mauda Leave a Comment

Conteúdo do Post:
  1. Classes Literais e Concretas
  2. Pattern Factory
  3. Criando a classe BilheteFactory
  4. Utilização da classe Factory
  5. Aplicações no Mundo Real
  6. finally{

Olá Pessoal, tudo bom?

Esse artigo é a continuação de uma série de artigos que estão relacionados a padrões de codificação ou Design Patterns. Mais especificamente esse artigo irá retratar o padrão Factory e como ele é aplicado em códigos Java.

Classes Literais e Concretas

Um padrão comum, até mesmo por questões de portabilidade em códigos Java é utilizar literais, ou seja, classes abstratas ou interfaces, para criação de atributos ou parâmetros de métodos. Isso é muito comum ao trabalhar com a biblioteca Collection do Java. Normalmente é criado um atributo do tipo List<?> e não um ArrayList<?> diretamente. Isso se deve ao fato de podermos, via Polimorfismo, passar qualquer instância de classe que em sua Hierarquia seja um List<?>. O código abaixo representa um método de ordenação de palavras cujo parâmetro é uma List<String>.

Java
1
2
3
4
5
6
7
8
9
10
11
12
//Utiliza bubble sort, mas ok eh só um exemplo :-)
public void ordenaPalavras(List<String> palavras){
for(int i = 0; i < palavras.size(); i++){
for(int j = i+1; j < palavras.size(); j++){
if(palavras.get(i).compareTo(palavras.get(j)) > 0){
String swap = palavras.get(i);
palavras.set(i, palavras.get(j));
palavras.set(j, swap);
}
}
}
}

E aqui temos uma chamada de teste para esse método:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
 
public classe OrdenacaoExemploTeste{
@Test
public void testeOrdenacao() {
List<String> array = new ArrayList<String>();
array.add("Teste");
array.add("Abacaxi");
array.add("Despites");
ordenaPalavras(array);
for (String string : array) {
System.out.println(string);
}
}
}

Esse teste foi construído para rodar na ferramenta JUnit. Caso não conheça a ferramenta há um tutorial aqui.

Repare na linha 09, ao invés de realizar um new em um List<String>, que é impossível já que List é uma interface, foi realizada uma instanciação de ArrayList. Caso fosse mudado o exemplo para LinkedList, iria funcionar também. O que acontece aqui é que uma classe Literal, necessariamente precisa de uma classe concreta.

Isso é muito importante quando temos uma hierarquia de classes considerável, por exemplo, uma classe Literal Ambiente, mas várias filhas, Casa Show, Cinema e Teatro. Dessa forma ao invés de termos métodos que recebem uma filha, por exemplo Cinema, é possível optar por receber uma classe pai, Ambiente. Podendo dessa forma reutilizar vários métodos. Isso é chamado de Princípio de Programação por Interface.

Esse princípio também pode ser aplicado para a criação dos objetos da hierarquia, utilizando o padrão Factory, assim se tivermos os seguintes itens:

  • Classes pai e filhas organizadas em uma hierarquia de herança ou implementação de interface.
  • Algumas maneiras de criar uma instância de uma classe filha.
  • Não existir a necessidade de conhecimento de como é a criação de uma classe filha.

Pattern Factory

A definição do padrão Factory, de acordo com o Livro de Design Patterns ((https://books.google.com.br/books?id=6oHuKQe3TjQC&redir_esc=y)) é o seguinte:

Padrão que define uma interface* para criar um objeto, mas permite às classes decidirem qual classe instanciar. Permite a uma classe deferir a instanciação para subclasses

*Essa interface não é uma interface Java, mas sim uma forma de criar um objeto, no nosso caso será uma classe Java.

Esse padrão é amplamente utilizado na produção de software, sendo baseado no padrão do Encapsulamento. Esse padrão também possui a característica de centralizar a criação de objetos dentro da hierarquia, tornando mais fácil manutenções sobre a criação de objetos e a inserção da criação de novos tipos de objetos, provendo um baixo acoplamento e alta coesão.

Assim o diagrama de classes que configura esse padrão está descrito na Figura 01:

Figura 01 – Diagrama de classes que representa o padrão Factory

A fim de facilitar a explicação, tomei a liberdade de criar um Enum que contém todos os tipos da hierarquia T. Esse enum é passado para o método getInstance(TypeT) da classe FactoryT, o qual através desse tipo irá retornar uma instância do tipo correspondente.

Difícil compreender utilizando esse diagrama? Sim o diagrama torna um pouco mais complicado o entendimento, por isso vamos fazer um exemplo, conforme mostra a Figura 02:

Figura 02 – Hierarquia Bilhete – Com enum e factory

É possível perceber que foi criado um Enum, de nome TipoBilhete, o qual contém valores do tipo Economica, Executiva e Primeira. Uma instância de um desses tipos é passado para o método getInstance(TipoBilhete) da classe BilheteFactory, o qual retorna uma instância de Economica, Executiva ou Primeira de acordo com o tipo. O restante da hierarquia é igual a qualquer outra hierarquia de classes Java, onde não nos alongaremos na explanação destas.

Agora vamos verificar como seria criada a classe BilheteFactory

Criando a classe BilheteFactory

Para criar uma classe Factory é necessário realizar os seguintes passos:

  • Criar um método, se possível estático, que retorne todas as instâncias de uma hierarquia.
  • Para facilitar a criação utilize um switch case para o enum.

Assim o código desta classe é representado abaixo:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
public class BilheteFactory {
  public static Bilhete getInstance(TipoBilhete enum){
    switch (enum) {
case ECONOMICA:
return new Economica();
case EXECUTIVA:
return new Executiva();
case PRIMEIRA:  
return new Primeira();
    }
    return null;
  }
}

Agora é necessário verificar como será a utilização desta classe.

Utilização da classe Factory

Para utilizar a classe é necessário apenas chamar o método getInstance(), como podemos verificar no exemplo:

Java
1
2
3
4
5
6
7
8
9
10
11
12
import org.junit.Assert;
import org.junit.Test;
 
public classe FactoryExemploTeste{
@Test
public void criar() {
Bilhete bilhete = BilheteFactory.getInstance(TipoBilhete.ECONOMICA);
Assert.assertNotNull(bilhete);
Assert.assertTrue(TipoBilhete.ECONOMICA.equals(bilhete.getTipo()));
}
}

Se o teste ficou verde significa que a classe está obtendo a instância da filha de Bilhete de forma correta.

Aplicações no Mundo Real

A utilização básica está justamente no fato de criar fábricas de classes para utilizarmos conforme a necessidade de nossos sistemas. Não há muito o que comentar, pois o próximo exemplo já explicitou a principal forma de utilização deste padrão.

finally{

Duvidas ou sugestões? Deixe seu feedback! Isso ajuda a saber a sua opinião sobre os artigos e melhorá-los para o futuro! Isso é muito importante!

Até um próximo post!

Filed Under: Java, Orientação a Objetos, Padrões de Projeto Tagged With: Construtores, Design Patterns, Factory, Java, Padrões de Projeto, UML

About Mauda

Mestre em Informática, Analista de Sistemas, Professor, SCJP e Baterista. Desde 2002 trabalhando no mundo Java e ensinando pessoas sobre desenvolvimento de sistemas. Mais informações

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Advertisements

Copyright © 2025 · Genesis Framework · WordPress · Log in