Você está na página 1de 15

Modelo de Artigo Revista MundoJava

Padres de Projeto em Java


Reutilizando o projeto de software
Peter Jandl Jr. (jandl@uol.com.br)
Atualmente no se concebe um processo de desenvolvimento de software srio sem a utilizao da orientao a objetos, pois esta permite agregar aos sistemas desenvolvidos sob seus paradigmas qualidades importantes como a extensibilidade e a reusabilidade [5]. Mas sua aplicao, por si s, no garante a obteno destas qualidades, dado que parece depender um pouco das linguagens e ferramentas empregadas no desenvolvimento e teste; muito das tcnicas usadas nas etapas de anlise e definio destes sistemas; e ainda mais das concepes de seus projetistas. Como usual que a experincia dos projetistas se mostre como fator preponderante no sucesso de qualquer projeto, muito desejvel compartilhar e transmitir o conhecimento inerente a estas experincias para outros profissionais, sejam eles iniciantes ou no. Mas como fazer isto? Uma resposta para esta questo se encontra na utilizao dos padres de projeto.

Introduo Analisando muitos casos de desenvolvimento, possvel notar que vrios dos problemas endereados so compreendidos apenas superficialmente, sem que sejam explorados em toda sua profundidade. Tambm comum que a documentao relacionada tanto ao problema como soluo encontrada esteja incompleta ou ausente. Portanto, uma parcela do problema permanece sem anlise, enquanto que uma parte do conhecimento e experincia adquiridos nestes projetos fica retida apenas por seus participantes, dificultando seu compartilhamento e transmisso para outros. Desta forma, problemas idnticos que se repetem em outros contextos no so reconhecidos como tal, consumindo tempo e recursos para a definio de solues que j haviam sido encontradas. Os padres de projeto, ou design patterns, vem despertando interesse da comunidade de projetistas de software por proporcionar elementos que conduzem ao reaproveitamento de solues para projetos e no apenas reutilizao de cdigo. Os padres do projeto permitem evidenciar os aspectos essenciais de problemas comuns, levando a sua compreenso mais

ampla, e orientando a construo de sistemas que exibam efetivamente as qualidades desejadas. Atravs da implementao de alguns padres de projeto em Java podemos verificar as vantagens de sua utilizao, ao mesmo tempo que passamos a conhecer solues robustas para certos problemas. Como motivao adicional destacamos que a plataforma Java se beneficia do uso intensivo dos padres de projeto [4]. Definindo os Padres de Projeto Um padro de projeto sistematicamente denomina, motiva e explica uma soluo genrica de projeto, aplicvel a um problema recorrente no projeto de sistemas orientados a objetos, descrevendo assim o prprio problema, a soluo, as aplicaes e conseqncias de sua adoo [3]. Esta definio enfatiza o entendimento dos aspectos fundamentais do problema, motivando o projeto na direo de uma soluo genrica e reutilizvel, pois cada padro responsvel pela soluo de um tipo de problema que ocorre repetidas vezes em nosso ambiente. Deste modo, solues corretas podem ser aperfeioadas e usadas novamente por outros desenvolvedores em situaes semelhantes. O desafio possibilitar a "transferncia" de conhecimentos dos projetistas mais experientes para os "novatos", acelerando seu amadurecimento profissional e ampliando as chances de criao de novas solues. Projetistas experientes evitam a construo de solues do incio ao fim, procurando reutilizar as partes semelhantes identificadas em sistemas existentes, de modo que a cada ciclo de uso destas solues sejam incorporadas novas caractersticas que as tornem melhor ou mais genricas. Mas isto s pode ser feito por profissionais maduros, que j tenham passado por tais experincias, e desde que exista documentao apropriada. Grande parte das metodologias de projeto enfatizam a soluo em si ("o que" e "como" fazer), deixando de lado o "por que" da soluo [1], fazendo que a documentao produzida no seja til para compartilhar o conhecimento adquirido. Mais importante do que a prpria soluo a descrio do problema e da forma com que uma soluo torna-se aplicvel ao mesmo, incluindo-se nisto as limitaes e conseqncias de seu emprego. Os padres de projeto pretendem preencher estas lacunas, tornando-se um mecanismo para a comunicao e o compartilhamento de conhecimento entre desenvolvedores, constituindo uma linguagem capaz de exprimir mais do que simples estruturas de dados, mdulos ou objetos, mas a articulao destes elementos em solues arquitetnicas para o software [3]. Quando um projetista se familiariza com vrios padres de projeto, ele adquire uma parcela da experincia daqueles que os desenvolveram; e com seu emprego evita reinventar solues existentes, permitindo concentrar esforos nos aspectos inditos do problema e tornando os sistemas assim desenvolvidos provavelmente mais robustos e confiveis.

Um Breve Histrico Em 1977 Christopher Alexander publica um catlogo contendo mais de 250 padres construtivos, que discutiam questes comuns da arquitetura, descrevendo em detalhe o problema e as justificativas de sua soluo. Algum tempo depois ele formaliza seu mtodo de descrio de padres e o racional de sua aplicao, defendendo que seu uso no limitaria os arquitetos s solues prescritas, mas garantiria a presena dos elementos fundamentais que exprimiam conceitos atemporais de qualidade. Com esta inspirao, Ward Cunnigham e Kent Beck, criaram cinco padres voltados para o desenvolvimento de interfaces de usurio, que proporcionaram grandes ganhos ao projeto onde foram aplicados. Tais resultados, apresentados em 1987, chamaram a ateno de muitos integrantes da comunidade de software, fazendo que o tema ganhasse destaque cada vez maior nas conferncias sobre orientao a objetos. Erich Gamma, Richard Helm, Raph Johnson e John Vlissides, que posteriormente se tornariam conhecidos como a GoF (Gang of Four), comeam a trabalhar juntos, publicando em 1995 o livro "Design Patterns: Elements of Reusable Object-Oriented Software" [3], at hoje uma referncia absoluta no tema. Desde ento os padres de projeto se tornaram conhecimento essencial para projetistas de software. Caractersticas dos Padres de Projeto Embora um padro de projeto seja a descrio de um problema, de uma soluo genrica e sua justificativa, isto no significa que qualquer soluo conhecida para um problema constitua um padro, pois existem caractersticas que sempre devem ser atendidas pelos padres [2][3]: devem descrever e justificar a soluo para um problema concreto e bem definido; a soluo descrita deve ser comprovada previamente; devem descrever relaes entre conceitos, mecanismos e estruturas existentes nos sistemas; e o problema tratado deve ocorrer em diferentes contextos, ou seja, se a soluo no tem aplicao em diferentes situaes ento no constitui um padro. Percebemos que os padres de projeto sustentam uma gama ampla de conceitos: permitem exprimir adequadamente concepes e estruturas que no so necessariamente objetos; capturam a evoluo e aprimoramento das solues, equilibrando seus pontos fortes e fracos; renem experincia em torno da soluo de um problema comum; e usualmente no constituem solues triviais. Tambm devem ser possvel sua utilizao independente ou em conjunto com outros padres, compondo assim linguagens de padres. Descrevendo Padres de Projeto Os padres de projeto podem constituir um catlogo de solues testadas, aprovadas e reutilizveis, definindo um vocabulrio especializado onde cada padro associado aos conceitos relativos a um tipo de problema e sua soluo. Assim necessrio estruturar sua documentao, sem se prender s linguagens de programao ou contextos particulares, sendo freqente sua descrio textual atravs de um roteiro padronizado conhecido como forma. Existem diversas formas (tais como Alexander, Gamma, Coplien etc.) que geralmente incluem: nome do padro de projeto, propsito, problema, contexto, dificuldades, limitaes ou restries, soluo, resultados, diagramas e exemplos [4]. O nome do padro um elemento importante, pois ser adotado pelos desenvolvedores como uma referncia descritiva do problema, sua soluo, caractersticas e conseqncias. As descries associadas ao propsito, motivao, aplicabilidade e conseqncias devem ser valorizadas, pois contm o

problema, racional da soluo, recomendaes e decorrncias de seu uso. A estrutura dos padres, seus participantes e inter-relacionamentos podem ser descritas atravs de diagramas UML. Tambm til listar outros padres relacionados e situaes reais de aplicao. Exemplos de Padres de Projeto Existem muitos padres de projeto, aplicveis em domnios diferentes da computao, mas nenhum estudo inicial sobre o assunto pode deixar de tratar, pelo menos alguns, dos 23 padres de projeto propostos pela GoF (na Tabela 1 lista exemplos dos mais utilizados). Aqui detalharemos os padres Singleton, Factory Method e Facade, muito teis e essenciais para o entendimento de outros padres, utilizando uma forma bastante resumida [4].
Tabela 1. Principais Padres de Projeto da GoF Nome do Padro Descrio Resumida Abstract Factory Permite criar famlias de objetos sem que suas classes sejam conhecidas diretamente. Bridge Separa uma abstrao de sua implementao, tornando-as independentes. Command Separa o acionador da ao, suportando operaes complexas. Composite Agrupa objetos em rvores, representando hierarquias do tipo todo/parte. Decorator Possibilita a adio dinmica de novas capacidades a objetos. Facade Prov uma interface nica e simples para um subsistema complexo com vrias interfaces. Factory Method Permite criar um objeto sem que sua classe seja diretamente conhecida. Iterator Oferece um meio padronizado para acessar elementos de uma estrutura de dados. Memento Possibilita salvar o estado de um objeto de modo que o mesmo possa ser restaurado. Observer Define um mecanismo de notificao para mltiplos objetos que dependem de um outro. Singleton Garante a criao de um nico objeto de uma classe especfica. State Cria objetos cujo comportamento se altera conforme seu estado. Strategy Permite que uma famlia de algoritmos seja utilizada de modo independente e seletivo. Visitor Define operaes independentes a serem realizadas sobre elementos de uma estrutura.

Singleton
Motivao, propsito e aplicabilidade

um padro de projeto simples que ilustra vrias caractersticas necessrias aos padres de projeto. considerado um padro de criao, pois est relacionado com o processo de criao de objetos, possuindo inmeras aplicaes e implementao bastante direta. O que motiva sua existncia o fato de que muitas aplicaes necessitam garantir a ocorrncia de uma nica instncia de classes especficas, pois tais objetos podem fazer uso de recursos cuja utilizao deve ser exclusiva, ou porque desejamos que os demais elementos do sistema compartilhem um nico objeto particular. Estas situaes ocorrem quando vrios subsistemas utilizam um nico arquivo de configurao, permitindo sua modificao concorrente; ou quando s devemos estabelecer uma conexo exclusiva com um banco de dados ou um sistema remoto, devendo ser compartilhada por vrias tarefas paralelas; dentre muitas outras. Ao mesmo tempo no queremos que os usurios destas classes zelem por esta condio de unicidade, mas desejamos oferecer acesso simples instncia nica que dever existir, portanto adicionaremos estas responsabilidades s classes que devero constituir um Singleton. Assim este padro tem como propsito garantir a existncia de uma instncia nica de uma classe especfica, a qual possa ser acessada de maneira global e uniforme.
Estrutura, participantes e conseqncias

A estrutura do Singleton, ilustrada na Figura 1, indica as caractersticas necessrias para que a classe desejada possua uma nica instncia. Percebemos que tal classe deve manter uma

referncia para uma instncia de seu prprio tipo e tambm deve implementar uma operao getInstance() responsvel pela criao de apenas um objeto e pelo retorno da referncia correspondente. Instncias de classes que implementam o padro Singleton s podero ser obtidas atravs desta operao.

Figura 1. Estrutura do padro de projeto Singleton

Implementao e exemplo

A implementao em Java deste padro, deve utilizar um campo privado e esttico do tipo da prpria classe para armazenar a referncia da nica instncia permitida, o qual deve ser inicializado de modo a indicar a inexistncia de tal instncia. Um mtodo esttico, cujo tipo de retorno tambm a prpria classe, prov o ponto nico de acesso a tal instncia. Se a operao de instanciao ocorrer apenas na primeira solicitao de um objeto da classe, garantimos a instncia nica ao mesmo tempo que a criao s ocorrer quanto estritamente necessrio (lazy instantiation). Como o Java suporta a clonagem de objetos, devemos declarar a classe como final, para impedir que suas subclasses possam implementar a interface Cloneable, possibilitando a duplicao de objetos atravs do mtodo clone(), o que romperia com as obrigaes deste padro. Caso a classe Singleton seja uma subclasse de outra que suporte a clonagem, ento o mtodo clone() deve ser sobreposto por outro que apenas lance a exceo CloneNotSupportedException, indicando a impossibilidade da realizao desta operao. Na Listagem 1 temos a implementao da classe DBConnection destinada a fornecer uma conexo nica para um banco de dados especfico, que obedece a caracterizao que fizemos do padro Singleton. Atravs do uso desta classe podemos reduzir a quantidade de recursos utilizada por uma aplicao durante o acesso ao banco de dados, garantindo uma nica conexo. Internamente a classe mantm uma referncia nica para um objeto de tipo Connection, criado pelo construtor privado declarado. Apenas atravs do mtodo getConnection() possvel obter a referncia para a conexo nica. Existe um mtodo adicional shutdown() criado para garantir que a conexo seja encerrada adequadamente. Note que so arbitrrias as definies de campos e mtodos adicionais dentro de uma classe que pretende ser um Singleton, devendo atender aos requisitos especficos da aplicao.
Listagem 1. Implementao de um Singleton
package jandl.pattern.singleton; import java.sql.*; public final class DBConnection { // referncia para instncia nica private static Connection instance = null; // construtor privado private DBConnection() throws ClassNotFoundException, SQLException { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

System.out.println("[Driver loaded]"); instance = DriverManager.getConnection("jdbc:odbc:Mamute"); System.out.println("[Connection done]"); } // fornece acesso a instncia nica public static Connection getConnection() throws ClassNotFoundException, SQLException { if (instance == null) { // lazy instantiation: s quando preciso new DBConnection(); } System.out.println("[Connection obtained]"); return instance; // retorna instncia nica da conexo } // encerra conexo adequadamente public static void shutdown() throws ClassNotFoundException, SQLException { if (instance != null) { instance.close(); instance = null; System.out.println("[Connection closed]"); } } }

Na Listagem 2 temos um exemplo simples que permite verificar o funcionamento do Singleton. Atravs do mtodo getConnection() da classe DBConnection obtemos uma conexo para o banco de dados (cujas strings referentes ao driver e url de conexo foram inclusas diretamente no cdigo da classe). Atravs desta conexo podem ser estabelecidas sesses com o banco de dados, o que permite a execuo de comandos SQL e processamento dos resultados obtidos. Tentativas de obteno de novas conexes retornaro uma referncia para o mesmo objeto, reduzindo a quantidade de recursos tomados do sistema.
Listagem 2. Teste do Singleton
package jandl.pattern.singleton; import java.sql.*; public class DBConnectionTest { public static void main(String a[]) throws Exception { Connection con; Statement stmt; // obtm conexo con = DBConnection.getConnection(); stmt = con.createStatement(); int r = stmt.executeUpdate( "INSERT INTO USERS VALUES('" + a[0] + "','"+ a[1] +"')" ); System.out.println(r + " row(s) affected"); stmt.close(); // obtm (a mesma) conexo con = DBConnection.getConnection(); stmt = con.createStatement(); ResultSet rs = stmt.executeQuery( "SELECT * FROM USERS" ); while (rs.next()) { System.out.println(rs.getString(1) + ":" + rs.getString(2)); } rs.close(); stmt.close(); // encerra conexo DBConnection.shutdown(); } }

Usos conhecidos e padres relacionados

A classe Runtime, da API do J2SE, possui um mtodo getRuntime() que retorna uma instncia da prpria classe, o qual permite o acesso ao ambiente de execuo por parte da aplicao. Como o ambiente nico, s pode existir uma instncia desta classe, assim claro que Runtime implementa o padro de projeto Singleton para cumprir com esta restrio. Outros usos deste padro esto associados ao acesso controlado de filas de impresso, portas de comunicao e outros recursos restritos do sistema. Tambm comum que este padro esteja associado a outros, tais como o Abstract Factory e o Facade. O padro Singleton pode ser modificado para que exista um nmero mximo de instncias de uma classe, caracterizando assim um pool de objetos, flexibilizando seu emprego nas situaes em que no necessrio garantir uma instncia nica, mas onde deve ser limitada a quantidade total de objetos e recursos utilizados. Factory Method
Motivao, propsito e aplicabilidade

Uma estratgia comum no desenvolvimento de sistemas utilizar uma classe como base para criao de vrias outras subclasses mais especializadas. A base desta hierarquia como uma interface comum para os tipos derivados, inteno que pode ser reforada tornando-a uma classe abstrata ou uma interface. Assim novos tipos podero ser adicionados hierarquia sem que seja afetado o cdigo existente. Por outro lado, como prever a adio de novos tipos nos trechos de cdigo onde objetos deve ser criados, isto , como escolher uma dentre as classes disponveis quando novas implementaes so incorporadas ao sistema? O padro Factory Method (ou Mtodo Fbrica) resolve este problema definindo uma interface para criao de objetos (os "produtos") e deixando que uma outra classe (a "fbrica") decida como ser a instanciao de objetos. Isto permite isolar as requisies de novos objetos de sua seleo e instanciao efetiva. Na implementao da classe "fbrica" deve existir um mtodo responsvel pela instanciao dos "produtos", o mtodo fbrica, que cria objetos pertencentes a hierarquia de classes em questo, sendo portanto um outro padro de criao. Podemos empregar este padro sempre que desejamos oferecer um servio de criao de objetos quando o conjunto de classes concretas deva ser modificado com a adio de novas classes. A nica exigncia para isso que as classes concretas sejam parte de uma mesma hierarquia, possibilitando a manipulao de seus objetos pela interface definida em sua base.
Estrutura, participantes e conseqncias

Atravs da Figura 2 podemos observar que existem quatro componentes na estrutura deste padro. IProduct especifica a interface comum para os tipos especializados que devero ser instanciados. Uma ou mais classes ProductImpl, que so as classes concretas que implementam a interface IProduct, dotando seus objetos de caractersticas prprias. A interface IFactory, que determina a operao correspondente ao mtodo fbrica propriamente dito, por exemplo, createProduct(), que retorna objetos do tipo genrico IProduct. A classe FactoryImpl implementa a interface de obteno de objetos, ou seja, a operao createProduct(), onde ocorre a seleo da classe concreta que ser utilizada para a criao de um objeto IProduct.

Figura 2. Estrutura do padro de projeto Factory Method

O uso deste padro separa a classe da aplicao das classes especficas, sendo que apenas no mtodo fbrica existem referncias diretas s classes especficas. Outra conseqncia que a adio de novas subclasses de produto exigir apenas a modificao do mtodo fbrica, tornando o cdigo mais robusto e manutenvel.
Implementao e exemplo

Inicialmente iremos nos concentrar nos produtos da fbrica, definindo a interface IConverter, a qual ser utilizada para a manipulao destes, como mostra a Listagem 3. Esta interface define o mtodo convert(double), cujo propsito permitir a converso de um valor numrico em outro segundo algum critrio. Todos os produtos da fbrica devero implementar tal interface, ou seja, suprir o mtodo convert(double), determinando assim uma converso especfica.
Listagem 3. Interface dos produtos
package jandl.pattern.factorymethod; public interface IConverter { public double convert (double value); }

Classes destinadas converso, por exemplo, de temperaturas, de moedas ou unidades de medida, poderiam implementar esta interface, tais como as exemplificadas na Listagem 4, onde temos conversores de temperatura entre as escalas Celsius, Farenheit e Kelvin que constituiriam possveis produtos fornecidos pela fbrica.
Listagem 4. Implementao dos produtos
// Conversor Celsius to Farenheit package jandl.pattern.factorymethod; public class C2F implements IConverter { public double convert(double value) { return 9*value/5 + 32; } } // Conversor Celsius to Kelvin

package jandl.pattern.factorymethod; public class C2K implements IConverter { public double convert(double value) { return value + 273; } } // Conversor Farenheit to Celsius package jandl.pattern.factorymethod; public class F2C implements IConverter { public double convert(double value) { return 5*(value - 32)/9; } } // Conversor Farenheit to Kelvin package jandl.pattern.factorymethod; public class F2K implements IConverter { public double convert(double value) { return 5*(value - 32)/9 + 273; } } // Conversor Kelvin to Celsius package jandl.pattern.factorymethod; public class K2C implements IConverter { public double convert(double value) { return value - 273; } } // Conversor Kelvin to Farenheit package jandl.pattern.factorymethod; public class K2F implements IConverter { public double convert(double value) { return 9*(value - 273)/5 + 32; } }

Respeitando a proposta do padro Factory Method, podemos definir uma interface que caracterize o mtodo fbrica propriamente dito. Na Listagem 5 temos uma sugesto para isto, onde o nico mtodo especificado ser createConverter(int,int), utilizado para solicitar a criao de novos produtos conforme os argumentos recebidos. O emprego de argumentos no mtodo fbrica constitui uma variante do padro, que neste caso, representa as unidades de entrada e sada dos conversores.
Listagem 5. Interface do mtodo fbrica
package jandl.pattern.factorymethod; public interface IConverterFactory { public IConverter createConverter(int inS, int outS); }

Uma fbrica de produtos pode ser criada implementando-se a interface IConverterFactory, (Listagem 6, ConverterFactoryImpl), de modo que, conforme as unidades indicadas como argumentos do mtodo createConverter(int,int), seja instanciado um conversor adequado. Devemos ressaltar que apenas a classe ConverterFactoryImpl conhece as classes concretas que constituem os produtos, pois os clientes da fbrica recebero instncias de objetos que sero genericamente usados atravs da interface de produto IConverter. Para tornar o uso

desta fbrica mais flexvel, foram adicionadas constantes e strings correspondentes s unidades suportadas. Caso no exista uma classe apropriada para um conversor das unidades indicadas, o mtodo fbrica retorna null, embora pudesse ter lanado uma exceo.
Listagem 6. Implementao da fbrica
package jandl.pattern.factorymethod; public class ConverterFactoryImpl implements IConverterFactory { // constantes de escalas disponveis public static final int CELSIUS=0, FARENHEIT=1, KELVIN=2; public static final String scales[] = { "Celsius", "Farenheit", "Kelvin" }; // mtodo fbrica public IConverter createConverter(int in, int out) { switch(in) { case CELSIUS: switch(out) { case FARENHEIT: return new C2F(); case KELVIN: return new C2K(); } break; case FARENHEIT: switch(out) { case CELSIUS: return new F2C(); case KELVIN: return new F2K(); } break; case KELVIN: switch(out) { case CELSIUS: return new K2C(); case FARENHEIT: return new K2F(); } break; } return null; } }

Na Listagem 7 temos uma aplicao de converso de unidades de temperatura que utiliza a fbrica para obter diferentes conversores, conforme a seleo de unidades. Observe que a aplicao no conhece as classes especficas e seus detalhes, restringindo-se aos elementos fornecidos pela fbrica. Alteraes nas implementaes dos conversores, bem como a adio de novos conversores podem ser realizadas livremente, concentrando as modificaes correspondentes na fbrica que isola, portanto, a aplicao cliente das implementaes dos produtos.
Listagem 7. Aplicao da fbrica
package jandl.pattern.factorymethod; import java.awt.*; import java.awt.event.*; import java.text.*; import javax.swing.*; public class ConverterUI extends JFrame { private JComboBox chScIn, chScOut; private JTextField tfValIn, tfValOut; private ConverterFactoryImpl factory = new ConverterFactoryImpl(); private DecimalFormat df = new DecimalFormat("#####.00"); public ConverterUI() { super("ConverterUI");

Container c = getContentPane(); c.setLayout(new GridLayout(3, 3, 2, 2)); // adio dos componentes no ContentPane c.add(new JLabel()); c.add(new JLabel("In")); c.add(new JLabel("Out")); c.add(new JLabel("Scale")); c.add(chScIn = new JComboBox(factory.scales)); c.add(chScOut = new JComboBox(factory.scales)); c.add(new JLabel("Value")); c.add(tfValIn = new JTextField()); c.add(tfValOut = new JTextField()); // listeners e ajustes nos componentes tfValIn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { doConvertion(); } }); tfValOut.setEditable(false); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setResizable(false); } private void doConvertion() { IConverter conv = factory.createConverter( chScIn.getSelectedIndex(), chScOut.getSelectedIndex()); try { double value = df.parse(tfValIn.getText()).doubleValue(); if (conv!=null) { value = conv.convert(value); } tfValOut.setText(df.format(value)); } catch (Exception e) { tfValIn.selectAll(); tfValIn.requestFocus(); Toolkit.getDefaultToolkit().beep(); tfValOut.setText(""); } } public static void main(String a[]) { new ConverterUI().setVisible(true); } }

comum o emprego do padro Factory Method combinado com outros padres, tais como o Singleton, para garantir uma instncia nica da fbrica, ou Abstract Factory, que generaliza ainda mais o processo de criao de objetos. Tambm possvel que fbricas forneam elementos que implementem outros padres, como Iterator ou Decorator. Existem muitos exemplos de utilizao deste padro na API do J2SE, tais como as classes javax.swing.BorderFactory, java.text.Collator e java.net.SocketFactory. Facade
Motivao, propsito e aplicabilidade

Existem circunstncias onde necessrio utilizar diversas classes diferentes para que uma tarefa possa ser completada, caracterizando uma situao onde uma classe cliente necessita utilizar objetos de um conjunto especfico de classes utilitrias que, em conjunto, compem um subsistema particular ou que representam o acesso a diversos subsistemas distintos. O uso deste conjunto variado de classes introduz naturalmente uma complexidade maior na tarefa executada pela classe cliente, pois cada classe utilitria tem uma interface prpria, dificultando sua organizao e codificao. O padro de projeto denominado Facade, conhecido tambm como Fachada, pretende reduzir a complexidade do relacionamento entre a

classe cliente e as demais classes utilitrias, fornecendo uma interface nica e simplificada para o acesso s interfaces das classes utilitrias. O Facade um padro de projeto considerado como estrutural, pois sua responsabilidade consiste na organizao de uma interface mais simples para permitir o uso de mltiplas outras interfaces, constituindo uma abstrao de alto nvel. Este padro aplicvel quando se deseja uma interface mais simples para um ou mais subsistemas complexos, sendo que esta nova interface uma espcie de viso particularizada dos subsistemas que encapsula. Tambm pode ser empregado para reduzir as dependncias entre o cliente e as classes existentes no subsistema, possibilitando isolar a classe do cliente das classes de implementao do subsistema, reduzindo assim a coeso do sistema.
Estrutura, participantes e conseqncias

A estrutura deste padro bastante simples, como mostra a Figura 3. A classe que constituir o Facade dever oferecer um conjunto de operaes que sejam suficientes para que seus clientes possam utilizar adequadamente o subsistema, embora sem conhecer as interfaces de seus componentes. As classes dos subsistemas devem implementar as funcionalidades especficas necessrias, realizando as tarefas do cliente por meio da delegao da classe Facade. Isto significa que os clientes no precisam acessar diretamente as classes do subsistema, nem necessitam conhec-las. Desta forma, modificaes realizadas nas classes do subsistema, incluindo-se nisto adio de novas classes e funcionalidades, podero passar despercebidas pelo cliente, desde que a interface do Facade seja mantida.

Figura 3. Estrutura do padro de projeto Facade

Implementao e exemplo

Implementar um Facade demanda definir um conjunto de operaes reduzido, que permita ocultar a complexidade inerente utilizao de vrias classes de um subsistema. Tomemos a questo do acesso a banco de dados utilizando as classes mais comuns do JDBC. Para que uma nica operao de consulta seja realizada, necessrio utilizarmos diversos objetos: atravs da classe DriverManager obtemos um objeto Connection; com este obtemos um objeto Statement; com o qual realizamos a consulta, fornecendo-nos um objeto ResultSet para que, finalmente, tenhamos acesso aos dados retornados. Um Facade simples poderia encapsular a manipulao destes objetos, retornando apenas um objeto independente como resposta a uma query (um consulta SQL realizada por meio de uma operao SELECT), como mostra a Listagem 8.

Listagem 8. Implementao de Facade


package jandl.pattern.facade; import jandl.pattern.singleton.*; import java.sql.*; import java.util.*; public class QueryFacade { private Connection con; // construtor public QueryFacade() { try { // usamos Singleton de conexo ao BD con = DBConnection.getConnection(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } // mtodo que encapsula consulta public List executeQuery(String query) { try { Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); ResultSetMetaData rsmd = rs.getMetaData(); int colsCount = rsmd.getColumnCount(); List result = new LinkedList(); while (rs.next()) { String row[] = new String[colsCount]; for(int i=0, j=1; i<colsCount; i++, j++) { row[i] = rs.getString(j); } result.add(row); } rs.close(); stmt.close(); return result; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } // mtodo que encapsula shutdown da conexo ao BD public void shutdown() { try { DBConnection.shutdown(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } }

O construtor de QueryFacade obtm uma conexo ao banco de dados atravs do Singleton de conexo (Listagem 1), evitando mltiplas conexes. Atravs do mtodo executeQuery(String) o cliente pode apenas indicar a consulta que deseja realizar, recebendo com resultado uma coleo do tipo List, cujos elementos so arrays de String, contendo cada um os dados correspondentes aos registro obtido na consulta. Estes elementos podem ser acessados atravs de um objeto Iterator (que na API J2SE representa a implementao do padro de mesmo nome e que permite navegar pelos elementos de uma estrutura de dados). No foi retornado o objeto ResultSet, pois o mesmo est vinculado ao objeto Statement utilizado, alm disso esta estratgia isola completamente o cliente das classes JDBC utilizadas na consulta. Na Listagem 9 temos uma aplicao de console que testa o Facade construdo, onde podemos notar que a realizao da consulta tornou-se mais simples

em relao forma convencional (usada na Listagem 2). O processamento dos dados toma o restante do cdigo, mas feito sem conhecimento especfico da coleo retornada (sabemos apenas que cada elemento um array de String contendo os dados de cada registro, informao essa associada ao Facade em si).
Listagem 9. Aplicao do Facade
package jandl.pattern.facade; import java.util.*; public class QueryFacadeTest { public static void main(String a[]) { // instanciao e uso do Facade QueryFacade qf = new QueryFacade(); List result = qf.executeQuery("SELECT * FROM USERS"); // processamento dos dados Iterator i = result.iterator(); StringBuffer data = new StringBuffer(); int c; while (i.hasNext()) { String row[] = (String[])i.next(); for(c=0; c<row.length-1; c++) { data.append(row[c]); data.append(","); } data.append(row[c]); data.append("\n"); } // exibio e finalizao System.out.println(data.toString()); qf.shutdown(); } }

Notamos que o emprego de um Facade pode reduzir significativamente a complexidade do cdigo utilizado para a realizao de tarefas associadas a vrios subsistemas ou mltiplas classes. O segredo deste padro est no projeto de uma interface flexvel para o Facade. Na API J2SE, a classe java.net.URL utiliza este padro em sua implementao. Para Saber Mais A referncia mxima no assunto ainda o livro Padres de Projeto, de E. Gamma; R. Helm; R. Johnson; e J. Vlissides (Bookman, 2000); mas os exemplos so apresentados em dialeto C++. Vrios livros sobre Java incluem captulos sobre padres de projeto, entre eles Mais Java, de Peter Jandl Jr. (Futura, 2003); e Sun Certified Enterprise Architect for J2EE: guia oficial de certificao, de P. Allen e J. Bambara (Campus, 2003). Existem tambm muitos links interessantes, entre eles: The Hillside Group Patterns Homepage http://hillside.net/patterns/ Appleton, B. Patterns and Software: Essential Concepts and Terminology http://www.cmcrossroads.com/bradapp/docs/patterns-intro.html Lea, D. Patterns-Discussion FAQ http://g.oswego.edu/dl/pd-FAQ/pd-FAQ.html

Consideraes Finais Atravs dos exemplos vistos, pudemos observar conceitualmente que o emprego dos padres de projeto pode melhorar de maneira substancial a arquitetura de uma soluo de software. No incio comum encararmos com certo ceticismo a quantidade extra de classes introduzidas pelos padres, mas tal esforo vale cada linha de cdigo construda, pois tais solues permitem isolar as partes de um projeto, tornando-as independentes e mais flexveis. O resultado um sistema mais robusto e mais simples de ser mantido e ampliado. Alm disso os padres representam um vocabulrio de alto nvel para a troca de experincias e conhecimento relacionados ao projeto de software. Embora no sejam uma soluo milagrosa, nem aplicvel todas as situaes, depois de estudados, os padres de projeto podero ser reconhecidos, combinados e aplicados com relativa e crescente facilidade, sem contar com a possvel descoberta de novos padres associados aos problemas abordados. Embora no tenhamos realizado aqui um estudo exaustivo dos padres de projeto, fica o convite para um aprofundamento no tema, pois eles so definitivamente importantes para o projeto de sistemas e tambm reforam algo que j sabamos: o quanto o Java moderno e adequado para o desenvolvimento de software orientado a objetos. Referncias
[1] BECK, Kent, JOHNSON, Ralph. "Patterns Generate Architectures" IN Proceedings of ECOOP'94 - European Conference on Object Oriented Programming, pp. 139-49, Bologna, Italy, July/1994, Springer-Verlag. [2] COPLIEN, James O. "Software Patterns". New York, NY (USA): SIGS Books, 1996. [3] GAMMA, Erich, HELM, Richard, JOHNSON, Ralph, VLISSIDES, John. "Padres de Projeto: Solues reutilizveis de software orientado a objetos". Porto Alegre, RS: Bookman, 2000. [4] JANDL, Peter Jr.. Mais Java. So Paulo, SP: Futura, 2003. [5] PAGE-JONES, Meilir. "Fundamentos do Desenho Orientado a Objetos com UML". So Paulo, SP: Makron Books, 2001.

Autor
Peter Jandl Jr. (jandl@uol.com.br) formado em engenharia eltrica pela Unicamp e mestre em educao pela USF. Leciona no ensino superior h 16 anos em cursos de engenharia da computao, cincia da computao e anlise de sistemas. Programador certificado Java pela Sun, autor dos livros Introduo ao Java e Mais Java. Hoje professor da Universidade So Francisco e coordenador do curso de Cincia da Computao da Faculdade de Jaguarina.

Você também pode gostar