PROJETO DE SOFTWARE
Padrão Criacional
Descrição
Os padrões de projeto classificados como criacionais caracterizam-se por se concentrar na melhor
forma de criar e manipular objetos dentro do programa.
Tradicionalmente a criação de objetos pode resultar em um alto grau de interdependência entre
várias partes do programa. Para ser capaz de instanciar um objeto em algum local do programa o
programador deve saber especificamente a qual classe esse objeto pertence. Quando modificações
são necessárias, por exemplo, pela necessidade de se estender o programa a outros tipos de objetos
muitas vezes são necessárias modificações em várias partes do programa.
Vamos analisar inicialmente o programa principal. Ele está representado pela classe Main. A classe
Main possui dois métodos: menuPrincipal() que basicamente oferece uma interface com o usuário
através do Console e o método estático main() que é o ponto de inicio da execução do programa.
package designpatterns;
import java.util.Scanner;
/**
* @author Plinio Vilela
* Exemplo adaptado do livro:
* Programacao Java com Enfase em Orientacao a Objetos
* Douglas Rocha Mendes
* Novatec - 2009
*/
public class Main {
Scanner teclado;
Outro ponto importante é que não precisamos instanciar a classe AutomovelFactory para utilizar o
seu método getAutomovel(). Isso é possível porque o método foi declarado como estático. Veja na
Figura 01 que o método está grifado, indicando que é um método estático.
Vamos analisar agora a classe AutomovelFactory.
package designpatterns;
public class AutomovelFactory {
public static Automovel getAutomovel(String nomeAutomovel){
Automovel newAuto = null;
try{
Class <?> classe = Class.forName("designpatterns."+nomeAutomovel);
newAuto = (Automovel)classe.newInstance();
}catch(Exception e){
if (e instanceof ClassNotFoundException)
System.out.println("Nao achei a classe...");
if (e instanceof InstantiationException)
System.out.println("Problemas na Instanciacao...");
if (e instanceof IllegalAccessException)
System.out.println("Problema de acesso ilegal...");
}
return newAuto;
}
}
E por fim, na Figura 05, um exemplo de classe filha. Nesse caso é a classe CrossFox, as outras são
análogas.
package designpatterns;
public class CrossFox extends Automovel{
public CrossFox(){
super("CrossFox",42000);
}
}
Exercícios
O exemplo utilizado para ilustrar a aplicação do padrão de projeto criacional Factory poderia ser
utilizado em uma pequena loja de veículos multimarca. O sistema fornece o preço do veículo dado o
seu nome. Responda as seguintes perguntas:
1) Implemente as classes apresentadas nesta apostila, incluindo as classes filhas que não foram
apresentadas (lembrando que elas são análogas à classe CrossFox).
2) Implemente uma modificação no programa para permitir que o lojista simplesmente digite o
nome do veículo que ele quer consultar e o sistema informa o preço do veículo, se esse veículo
existir, ou uma mensagem dizendo que o veículo não está cadastrado caso ele não exista. Dica:
para implementar essa modificação apenas uma classe precisa ser modificada.
3) Considerando a versão do programa apresentada originalmente na apostila quais seriam as
modificações necessárias para se incluir um novo veículo para ser tratado pelo programa?
Explique.
4) Considerando a versão do programa implementada no exercício 2. Quais seriam as modificações
necessárias para se incluir um novo veículo no programa?
5) Suponha que agora a loja queira trabalhar também com o Fox, inclua esse veículo no programa,
considerando a versão implementada no exercício 2.
O exemplo da Figura 06 demonstra a utilização do padrão Singleton. Nesse caso criamos uma
Lista Ligada para armazenar objetos de um mesmo tipo. Cada objeto guarda uma referência para o
próximo objeto da lista. Caso não haja mais objetos na lista a referência é null.
Observe que existe apenas um método construtor, privado e sem parâmetros. Um método
getInstance() foi criado para permitir o acesso a um objeto em particular, a cabeça da lista chamada
de head. O atributo next indica qual é o próximo objeto da lista, caso a lista esteja vazia o atributo
next do objeto head será null.
Ao inserirmos o primeiro objeto na lista o método insert() deverá ser chamado. Nesse método
buscamos pelo último objeto na lista (ou seja, aquele cujo atributo next seja null) e então fazemos
com que o next desse objeto passe a ser o novo objeto sendo inserido.
O padrão Singleton é utilizado para garantir que existe apenas uma cabeça da lista. Observe que no
método main() nenhum objeto da classe ListaLigada é instanciado diretamente.
O padrão de projeto Singleton deve ser usado com cuidado em aplicações Multithread. Se duas
threads executam o método de criação ao mesmo tempo quando um objeto ainda não existe, ambas
deveriam verificar se um objeto já existe e apenas um deveria ser criado. Para evitar problemas na
criação de objetos nesse ambiente de programação, o método que cria o objeto deve ser executado
como um operação mutuamente exclusiva (bloco synchronized).
Exercícios
O exemplo anterior ilustra a aplicação do padrão Singleton. Responda as seguintes perguntas:
6) Implemente a classe apresentada na Figura 06.
7) A classe da Figura 06 possui um método estático main(). Suponha que esse método não
estivesse incluído nessa classe, mas sim em uma outra classe chamada PrincipalLista. O
programa continuaria funcionado? Faça essa modificação.
8) Modifique o programa para permitir que os novos objetos adicionados à lista sejam inseridos
como sendo o primeiro elemento da lista e não o último.
9) Faça uma modificação no programa para permitir que os objetos inseridos na lista sejam
inseridos em ordem alfabética do nome.
10) Seria possível percorrer todos os elementos da lista caso não existisse o método showAll()?
Explique.