|
|
(25 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| {{TOCright}}O padrão "simple" factory fornece uma forma de criar objectos a partir de uma descrição externa.
| | #REDIRECT [[ist:"Simple" Factory (padrão de desenho)]] |
| | |
| == Exemplo ==
| |
| | |
| Neste exemplo, apresenta-se a criação dinâmica de objectos de um determinado tipo, a partir de uma descrição textual desses objectos.
| |
| | |
| Este exemplo utiliza [[Informação de Tipos em Tempo de Execução (Java)|informação de tipos em tempo de execução]], mas qualquer outro que realizasse a mesma função por outras vias seria admissível.
| |
| | |
| === Introdução ===
| |
| Considere-se o ficheiro <tt>obras.txt</tt>, contendo descrições de DVDs (título e realizador) e de Livros (título, autor e [[wikipedia:ISBN|ISBN]]):
| |
| DVD:Era uma vez na amadora:Fernando Fonseca
| |
| DVD:Lumiar selvagem:Pedro Fonseca
| |
| Livro:A arte de sobreviver no 36:Joao Fonseca:1234567890
| |
| Livro:Bairro alto e o budismo zen:Zun Tse Fonseca:1234567891
| |
| DVD:48 horas para o exame:Orlando Fonseca
| |
| Livro:Lux e o insucesso escolar - Uma visao matematica:Carlos Alberto Fonseca:1234567892
| |
| | |
| A ideia da aplicação que se descreve de seguida é a leitura de cada linha como se da criação de um objecto se tratasse. Assim, o primeiro campo (os campos são separados por "<tt>:</tt>") define a classe do objecto e os restantes campos são passados como argumentos ao constructor da classe. Pretende-se ainda que a implementação seja suficientemente flexível para que resista à utilização de descrições erradas ou de descrições de objectos desconhecidos.
| |
| | |
| === Interfaces ===
| |
| | |
| Além dos aspectos acima, cada obra é classificada com uma ou mais interfaces, sendo o seu comportamento definido por elas.
| |
| | |
| <java5>
| |
| interface Folheável {
| |
| void folhear();
| |
| }
| |
| </java5>
| |
| | |
| <java5>
| |
| interface Legível {
| |
| void ler();
| |
| }
| |
| </java5>
| |
| | |
| <java5>
| |
| interface Rodopiável {
| |
| void rodopiar();
| |
| }
| |
| </java5>
| |
| | |
| Estas interfaces não são realmente utilizadas para os aspectos de criação dos objectos, mas permitem ilustrar a utilização de código específico em conjunto com código genérico.
| |
| | |
| === A classe de base ===
| |
| | |
| A classe de base de todas as entidades a criar é <tt>Obra</tt>. Esta classe, por um lado, impõe às suas subclasses a definição do método <tt>processa</tt> e, por outro, recorrendo a uma fábrica simples que, fazendo uso de informação de tipos em tempo de execução, permite criar instâncias das suas subclasses, de acordo com uma descrição passada como argumento (<tt>cria</tt>).
| |
| | |
| <java5>
| |
| import java.util.ArrayList;
| |
| import java.lang.reflect.Constructor;
| |
| import java.lang.reflect.InvocationTargetException;
| |
| | |
| public abstract class Obra {
| |
| static { System.out.println("Carregamento da classe Obra"); }
| |
| | |
| public abstract void processa();
| |
| | |
| static Obra cria(String dsc) {
| |
| String dados[] = dsc.split(":");
| |
| try {
| |
| ArrayList<String> ctorargs = new ArrayList<String>(dados.length-1);
| |
| Class tipo = Class.forName(dados[0]);
| |
| for (int ix = 1; ix < dados.length; ix++)
| |
| ctorargs.add(ix-1, dados[ix]);
| |
| Constructor ctor = tipo.getConstructors()[0]; // hack? só existe um...
| |
| return (Obra)ctor.newInstance(ctorargs.toArray());
| |
| }
| |
| catch (ClassNotFoundException e) { // forName
| |
| System.err.println("!! TIPO DE OBRA DESCONHECIDO !!");
| |
| System.err.println(e);
| |
| return null;
| |
| }
| |
| catch (InstantiationException e) { // newInstance
| |
| System.err.println("!! TIPO DE OBRA ABSTRACTO !!");
| |
| System.err.println(e);
| |
| return null;
| |
| }
| |
| catch (IllegalAccessException e) { // newInstance
| |
| System.err.println("!! TIPO DE OBRA SEM CONSTRUCTOR ACESSÍVEL!!");
| |
| System.err.println(e);
| |
| return null;
| |
| }
| |
| catch (IllegalArgumentException e) { // newInstance
| |
| System.err.println("!! TIPO DE OBRA MAL DESCRITO !!");
| |
| System.err.println(e);
| |
| return null;
| |
| }
| |
| catch (InvocationTargetException e) { // newInstance
| |
| System.err.println("!! TIPO DE OBRA COM CONSTRUCTOR EM APUROS !!");
| |
| System.err.println(e);
| |
| return null;
| |
| }
| |
| }
| |
| | |
| }
| |
| </java5>
| |
| | |
| Note-se o tratamento de várias excepções, em particular, o tratamento da excepção <tt>ClassNotFoundException</tt>, que tem, neste contexto especial, um significado para a aplicação algo distinto do habitual.
| |
| | |
| Note-se ainda o tratamento de <tt>InvocationTargetException</tt>, que permite lidar com as excepções específicas do constructor da obra em causa (''exception chaining'').
| |
| | |
| === As classes das obras ===
| |
| | |
| Para DVDs:
| |
| <java5>
| |
| public class DVD extends Obra implements Rodopiável, Legível {
| |
| static { System.out.println("Carregamento da classe DVD"); }
| |
| | |
| String _título;
| |
| String _realizador;
| |
| | |
| public DVD(String título, String realizador) {
| |
| _título = título;
| |
| _realizador = realizador;
| |
| }
| |
| | |
| public String toString() { return "DVD:" + _título + ":" + _realizador; }
| |
| public void ler() { System.out.println("LER " + this); }
| |
| public void rodopiar() { System.out.println("RODOPIAR " + this); }
| |
| | |
| public void processa() { rodopiar(); ler(); }
| |
| }
| |
| </java5>
| |
| | |
| Para livros:
| |
| <java5>
| |
| public class Livro extends Obra implements Folheável, Legível {
| |
| static { System.out.println("Carregamento da classe Livro"); }
| |
| | |
| String _título;
| |
| String _autor;
| |
| String _isbn;
| |
| | |
| public Livro(String título, String autor, String isbn) {
| |
| _título = título;
| |
| _autor = autor;
| |
| _isbn = isbn;
| |
| }
| |
| | |
| public String toString() { return "Livro:" + _título + ":" + _autor + ":" + _isbn; }
| |
| public void ler() { System.out.println("LER " + this); }
| |
| public void folhear() { System.out.println("FOLHEAR " + this); }
| |
| | |
| public void processa() { folhear(); ler(); }
| |
| }
| |
| </java5>
| |
| | |
| === Aplicação exemplo ===
| |
| | |
| Esta aplicação lê o ficheiro de obras (propriedade <tt>obras</tt>) e processa cada linha, criando os objectos correspondentes. Depois de lidas, as obras são processadas (uniformemente).
| |
| <java5>
| |
| import java.util.ArrayList;
| |
| import java.io.BufferedReader;
| |
| import java.io.FileReader;
| |
| import java.io.IOException;
| |
|
| |
| public class Teste {
| |
| public static void main(String[] args) throws IOException {
| |
| String entrada = System.getProperty("obras", "obras.txt");
| |
| BufferedReader r = new BufferedReader(new FileReader(entrada));
| |
| String linha;
| |
| ArrayList<Obra> obras = new ArrayList<Obra>();
| |
| while ((linha = r.readLine()) != null) {
| |
| Obra o = Obra.cria(linha);
| |
| obras.add(o);
| |
| System.out.println(o);
| |
| }
| |
| r.close();
| |
| System.out.println("****************");
| |
| for (Obra o: obras) o.processa();
| |
| }
| |
| }
| |
| </java5>
| |
| | |
| A saída da aplicação de teste é a que se apresenta. Note-se a ordem de carregamento das classes.
| |
| | |
| '''% java -Dobras=obras.txt Teste'''
| |
| <font color="green">Carregamento da classe Obra</font>
| |
| <font color="green">Carregamento da classe DVD</font>
| |
| DVD:Era uma vez na amadora:Fernando Fonseca
| |
| DVD:Lumiar selvagem:Pedro Fonseca
| |
| <font color="green">Carregamento da classe Livro</font>
| |
| Livro:A arte de sobreviver no 36:Joao Fonseca:1234567890
| |
| Livro:Bairro alto e o budismo zen:Zun Tse Fonseca:1234567891
| |
| DVD:48 horas para o exame:Orlando Fonseca
| |
| Livro:Lux e o insucesso escolar - Uma visao matematica:Carlos Alberto Fonseca:1234567892
| |
| ****************
| |
| RODOPIAR DVD:Era uma vez na amadora:Fernando Fonseca
| |
| LER DVD:Era uma vez na amadora:Fernando Fonseca
| |
| RODOPIAR DVD:Lumiar selvagem:Pedro Fonseca
| |
| LER DVD:Lumiar selvagem:Pedro Fonseca
| |
| FOLHEAR Livro:A arte de sobreviver no 36:Joao Fonseca:1234567890
| |
| LER Livro:A arte de sobreviver no 36:Joao Fonseca:1234567890
| |
| FOLHEAR Livro:Bairro alto e o budismo zen:Zun Tse Fonseca:1234567891
| |
| LER Livro:Bairro alto e o budismo zen:Zun Tse Fonseca:1234567891
| |
| RODOPIAR DVD:48 horas para o exame:Orlando Fonseca
| |
| LER DVD:48 horas para o exame:Orlando Fonseca
| |
| FOLHEAR Livro:Lux e o insucesso escolar - Uma visao matematica:Carlos Alberto Fonseca:1234567892
| |
| LER Livro:Lux e o insucesso escolar - Uma visao matematica:Carlos Alberto Fonseca:1234567892
| |
| | |
| [[category:OOP]]
| |