|
|
(28 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.
| |
| | |
| <span style="font-weight: bold;">interface</span> Folheável {
| |
| <span style="color: #800000;">void</span> <span style="color: #000080;">folhear</span>();
| |
| }
| |
| | |
| <span style="font-weight: bold;">interface</span> Legível {
| |
| <span style="color: #800000;">void</span> <span style="color: #000080;">ler</span>();
| |
| }
| |
| | |
| <span style="font-weight: bold;">interface</span> Rodopiável {
| |
| <span style="color: #800000;">void</span> <span style="color: #000080;">rodopiar</span>();
| |
| }
| |
| | |
| 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:
| |
| | |
| <b>public class</b> DVD <b>extends</b> Obra <b>implements</b> Rodopiável, Legível {
| |
| <span style="color: #800000;">static</span> { <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">out</span>.<span style="color: #000080;">println</span>(<span style="color: #dd0000;">"Carregamento da classe DVD"</span>); }
| |
|
| |
| <span style="font-weight: bold;color: #0095ff;">String</span> _título;
| |
| <span style="font-weight: bold;color: #0095ff;">String</span> _realizador;
| |
|
| |
| <b>public</b> <span style="color: #000080;">DVD</span>(<span style="font-weight: bold;color: #0095ff;">String</span> título, <span style="font-weight: bold;color: #0095ff;">String</span> realizador) {
| |
| _título = título;
| |
| _realizador = realizador;
| |
| }
| |
|
| |
| <b>public</b> <span style="font-weight: bold;color: #0095ff;">String</span> <span style="color: #000080;">toString</span>() { <b>return</b> <span style="color: #dd0000;">"DVD:"</span> + _título + <span style="color: #dd0000;">":"</span> + _realizador; }
| |
| <b>public</b> <span style="color: #800000;">void</span> <span style="color: #000080;">ler</span>() { <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">out</span>.<span style="color: #000080;">println</span>(<span style="color: #dd0000;">"LER "</span> + <b>this</b>); }
| |
| <b>public</b> <span style="color: #800000;">void</span> <span style="color: #000080;">rodopiar</span>() { <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">out</span>.<span style="color: #000080;">println</span>(<span style="color: #dd0000;">"RODOPIAR "</span> + <b>this</b>); }
| |
|
| |
| <b>public</b> <span style="color: #800000;">void</span> <span style="color: #000080;">processa</span>() { <span style="color: #000080;">rodopiar</span>(); <span style="color: #000080;">ler</span>(); }
| |
| }
| |
| | |
| Para livros:
| |
| | |
| <b>public class</b> Livro <b>extends</b> Obra <b>implements</b> Folheável, Legível {
| |
| <span style="color: #800000;">static</span> { <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">out</span>.<span style="color: #000080;">println</span>(<span style="color: #dd0000;">"Carregamento da classe Livro"</span>); }
| |
|
| |
| <span style="font-weight: bold;color: #0095ff;">String</span> _título;
| |
| <span style="font-weight: bold;color: #0095ff;">String</span> _autor;
| |
| <span style="font-weight: bold;color: #0095ff;">String</span> _isbn;
| |
|
| |
| <b>public</b> <span style="color: #000080;">Livro</span>(<span style="font-weight: bold;color: #0095ff;">String</span> título, <span style="font-weight: bold;color: #0095ff;">String</span> autor, <span style="font-weight: bold;color: #0095ff;">String</span> isbn) {
| |
| _título = título;
| |
| _autor = autor;
| |
| _isbn = isbn;
| |
| }
| |
|
| |
| <b>public</b> <span style="font-weight: bold;color: #0095ff;">String</span> <span style="color: #000080;">toString</span>() { <b>return</b> <span style="color: #dd0000;">"Livro:"</span> + _título + <span style="color: #dd0000;">":"</span> + _autor + <span style="color: #dd0000;">":"</span> + _isbn; }
| |
| <b>public</b> <span style="color: #800000;">void</span> <span style="color: #000080;">ler</span>() { <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">out</span>.<span style="color: #000080;">println</span>(<span style="color: #dd0000;">"LER "</span> + <b>this</b>); }
| |
| <b>public</b> <span style="color: #800000;">void</span> <span style="color: #000080;">folhear</span>() { <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">out</span>.<span style="color: #000080;">println</span>(<span style="color: #dd0000;">"FOLHEAR "</span> + <b>this</b>); }
| |
|
| |
| <b>public</b> <span style="color: #800000;">void</span> <span style="color: #000080;">processa</span>() { <span style="color: #000080;">folhear</span>(); <span style="color: #000080;">ler</span>(); }
| |
| }
| |
| | |
| === 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).
| |
| | |
| <b>import</b><span style="color: #808000;"> java.util.ArrayList;</span>
| |
| <b>import</b><span style="color: #808000;"> java.io.BufferedReader;</span>
| |
| <b>import</b><span style="color: #808000;"> java.io.FileReader;</span>
| |
| <b>import</b><span style="color: #808000;"> java.io.IOException;</span>
| |
|
| |
| <b>public class</b> Teste {
| |
| <b>public</b> <span style="color: #800000;">static</span> <span style="color: #800000;">void</span> <span style="color: #000080;">main</span>(<span style="font-weight: bold;color: #0095ff;">String</span>[] args) <b>throws</b> <span style="font-weight: bold;color: #0095ff;">IOException</span> {
| |
| <span style="font-weight: bold;color: #0095ff;">String</span> entrada = <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">getProperty</span>(<span style="color: #dd0000;">"obras"</span>, <span style="color: #dd0000;">"obras.txt"</span>);
| |
| <span style="font-weight: bold;color: #0095ff;">BufferedReader</span> r = <b>new</b> <span style="font-weight: bold;color: #0095ff;">BufferedReader</span>(<b>new</b> <span style="font-weight: bold;color: #0095ff;">FileReader</span>(entrada));
| |
| <span style="font-weight: bold;color: #0095ff;">String</span> linha;
| |
| <span style="font-weight: bold;color: #0095ff;">ArrayList</span><Obra> obras = <b>new</b> <span style="font-weight: bold;color: #0095ff;">ArrayList</span><Obra>();
| |
| <b>while</b> ((linha = r.<span style="color: #000080;">readLine</span>()) != <b>null</b>) {
| |
| Obra o = Obra.<span style="color: #000080;">cria</span>(linha);
| |
| obras.<span style="color: #000080;">add</span>(o);
| |
| <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">out</span>.<span style="color: #000080;">println</span>(o);
| |
| }
| |
| r.<span style="color: #000080;">close</span>();
| |
| <span style="font-weight: bold;color: #0095ff;">System</span>.<span style="color: #000080;">out</span>.<span style="color: #000080;">println</span>(<span style="color: #dd0000;">"****************"</span>);
| |
| <b>for</b> (Obra o: obras) o.<span style="color: #000080;">processa</span>();
| |
| }
| |
| }
| |
| | |
| 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]]
| |