Anda di halaman 1dari 6

ASSUNTO: DESIGN PATTERNS

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.

Padrão de Projeto Factory


Este padrão de projeto permite que novas classes sejam adicionadas ao programa sem haver a
necessidade de modificações em várias partes desse programa. Basta escrever uma nova classe, que
o programa vai passar a funcionar com essa nova classe praticamente sem nenhuma modificação.

Figura 01 - Diagrama de Classes Exemplo do Padrão Factory.


A Figura 01 mostra um exemplo de aplicação do padrão Factory. Nesse exemplo temos um
programa que utiliza objetos das classes Polo, CrossFox, Corsa e Celta. Cada uma dessas classes
são classes-filha da classe mãe Automovel. Para permitir que a classe Main fique independente das
classes especializadas a manipulação dos objetos é feita utilizando-se exclusivamente a classe mãe
Automovel.

PÁGINA 1 DE 6 PROF. DR. PLÍNIO VILELA


ASSUNTO: DESIGN PATTERNS PROJETO DE SOFTWARE

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;

public void menuPrincipal(){


teclado = new Scanner(System.in);
int iTipo = 0;
final String
vNomesCarros[] = {"Corsa","Celta","Polo","CrossFox","Corolla","Clio"};
while(iTipo != (vNomesCarros.length+1)){
Automovel auto = null;
for(int i =0; i<vNomesCarros.length; i++){
System.out.println((i+1)+" - "+vNomesCarros[i]);
}
System.out.println((vNomesCarros.length+1)+" - Fim\n");
System.out.println("Escolha o carro e analise seu preco: ");
iTipo = teclado.nextInt();
if((iTipo>0)&&(iTipo<=vNomesCarros.length)){
auto = AutomovelFactory.getAutomovel(vNomesCarros[iTipo-1]);
System.out.println(vNomesCarros[iTipo-1]+" - Preco= "+auto.getPreco());
}
}
}

public static void main(String[] args) {


(new Main()).menuPrincipal();
}
}

Figura 02 - Classe Main


Alguns detalhes importantes devem ser considerados na classe Main. A lista de carros que são
manipuladas pelo sistema é armazenada em um vetor de Strings. Essa lista é utilizada pelo método
menuPrincipal() para mostrar ao usuário do sistema quais são os carros que ele pode escolher para
verificar o preço. Tradicionalmente a numeração de itens apresentados para seres humanos inicia
em 1, mas em linguagens de programação tradicionalmente o índice de vetores e outros tipos de
estruturas iniciam em 0. No programa da Figura 02 um cuidado especial é tomado em relação a
isso. Os valores de seleção mostrados e lidos do usuário iniciam em 1, mas o índice do vetor continua
iniciando em 0.
Observe que o único ponto onde o objeto específico da classe Automovel é utilizado é quando o seu
preco é lido “auto.getPreco()”. Se olharmos a Figura 01 observamos que o método getPreco() está
presente na classe mãe Automovel. Ela retorna o valor do atributo valorAutomovel, que é definido
individualmente em cada uma das classes filha.
Mas de onde obtemos a instância de Automovel que está sendo utilizada? Observe o comando “auto
= AutomovelFactory.getAutomovel(vNomesCarros[iTipo-1]);” a instância do objeto é retornada
pelo método estático getAutomovel() da classe AutomovelFactory. Ela recebe uma String com o
nome do automovel e retorna uma instância do objeto correspondente.
PÁGINA 2 DE 6 PROF. DR. PLÍNIO VILELA
ASSUNTO: DESIGN PATTERNS PROJETO DE SOFTWARE

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

Figura 03 - Classe AutomovelFactory


A classe AutomovelFactory possui apenas o método estático getAutomovel() que recebe uma
String como parâmetro, indicando o nome da classe especializada de Automovel cuja instância
deverá ser retornada.
Utilizamos o mecanismo de reflexão do Java para criar uma instância de uma classe especial em Java
chamada Class, essa classe pode representar qualquer classe que você tenha em seu sistema
bastando apenas passar para ela o nome (uma String) da classe que você quer representar. Tendo
em mãos um objeto da classe Class podemos solicitar que uma instância do objeto da classe
representada seja criada. Isso é feito através do método newInstance() da classe Class.
Se não houver nenhuma exceção, como por exemplo a classe não ser encontrada, um objeto é
retornado. No nosso caso os objetos serão das classes filha Polo, CrossFox, Corsa, etc... já que
serão essas Strings que serão passadas como parâmetro na variável nomeAutomovel.
O padrão Factory é basicamente definido pelo uso dessa classe, uma vez que as classes que faltam
apenas definem uma hierarquia de classes tradicional. Veja na Figura 04 a classe Automovel.
package designpatterns;
public class Automovel {
private double preco;
private String nome;
public Automovel(String _nome, double _preco){
nome = _nome;
preco = _preco;
}
public double getPreco(){
return preco;
}
public String getNome(){
return nome;
}
}

Figura 04 - Classe Automovel

PÁGINA 3 DE 6 PROF. DR. PLÍNIO VILELA


ASSUNTO: DESIGN PATTERNS PROJETO DE SOFTWARE

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);
}
}

Figura 05 - Classe CrossFox


Neste exemplo simples a classe especializada apenas invoca o construtor da classe mãe passando
para ele os parâmetros nome e preço.

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.

PÁGINA 4 DE 6 PROF. DR. PLÍNIO VILELA


ASSUNTO: DESIGN PATTERNS PROJETO DE SOFTWARE

Padrão de Projeto Singleton


O padrão de projeto Singleton é usado para restringir a instanciação de uma classe para apenas um
objeto. Assim teremos um ponto comum e global para acesso ao objeto. O padrão de projeto
Singleton é implementado pela criação de uma classe com um método público que deve criar um
objeto dessa classe caso nenhum outro exista. Se um objeto já existir, esse método deve retornar
uma referência ao objeto já criado. Para garantir que não seja possível criar objetos de outra forma,
devemos criar apenas um construtor (sem argumentos) e torná-lo private.
Há situações nas quais precisamos racionalizar um recurso em nosso sistema ou, ainda, nas quais
apenas um objeto é necessário. Assim, para que essas regras sejam garantidas, usamos o conceito do
padrão de projeto Singleton.
package designpatterns;
import java.util.Scanner;
public class ListaLigada {
private static ListaLigada head;
private ListaLigada next;
private String nome;
private ListaLigada(){
nome = "";
}
public static ListaLigada getInstance(){
if(head==null){
head = new ListaLigada();
}
return head;
}
public void insert(String nome){
ListaLigada temp = getInstance();
while(temp.next!=null){
temp = temp.next;
}
temp.next = new ListaLigada();
temp.next.setNome(nome);
}
public void setNome(String nome){
this.nome = nome;
}
public void showAll(){
ListaLigada temp = getInstance();
while(temp.next!=null){
temp = temp.next;
System.out.println(temp.nome);
}
}

public static void main(String[] args) {


ListaLigada head = ListaLigada.getInstance();
Scanner teclado = new Scanner(System.in);
System.out.println("Digite os nomes (fim - para encerrar):");
String nome = teclado.nextLine();
while(!nome.equals("fim")){
head.insert(nome);
nome = teclado.nextLine();
}
head.showAll();
}
}

Figura 06 - Classe ListaLigada

PÁGINA 5 DE 6 PROF. DR. PLÍNIO VILELA


ASSUNTO: DESIGN PATTERNS PROJETO DE SOFTWARE

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.

PÁGINA 6 DE 6 PROF. DR. PLÍNIO VILELA

Anda mungkin juga menyukai