Easy-java 056 Zxcderty

June 4, 2018 | Author: dhhiego | Category: Use Case, Class (Computer Programming), Unified Modeling Language, Software, Programming Language
Report this link


Description

Assine agora e tenha acesso a todo o conteúdo da DevMedia: www.devmedia.com.br/mvp Edição 56 • 2015 • ISSN 2173625-4 Fale com o Editor! Atendimento ao leitor EXPEDIENTE A DevMedia possui uma Central de Atendimento on-line, onde você É muito importante para a equipe saber o que você está achando da revista: que tipo de artigo você gostaria de ler, que artigo você mais gostou e qual pode tirar suas dúvidas sobre serviços, enviar críticas e sugestões e artigo você menos gostou. Fique a vontade para entrar em contato com os falar com um de nossos atendentes. Através da nossa central também editores e dar a sua sugestão! Editor é possível alterar dados cadastrais, consultar o status de assinaturas Se você estiver interessado em publicar um artigo na revista ou no site e conferir a data de envio de suas revistas. Acesse www.devmedia. Easy Java Magazine, entre em contato com o editor, informando o título e Eduardo Spínola ([email protected]) com.br/central, ou se preferir entre em contato conosco através do mini-resumo do tema que você gostaria de publicar: telefone 21 3382-5038. Consultor Técnico Diogo Souza ([email protected]) Publicidade [email protected] – 21 3382-5038 Eduardo Oliveira Spínola Produção eduspinola.wordpress.com Jornalista Responsável Kaline Dolabella - JP24185 Anúncios – Anunciando nas publicações e nos sites do Grupo DevMedia, você divulga sua marca ou produto para mais de 100 mil desenvolvedores @eduspinola / @Java_Magazine Capa e Diagramação Romulo Araujo de todo o Brasil, em mais de 200 cidades. Solicite nossos Media Kits, com detalhes sobre preços e formatos de anúncios. Sumário Conteúdo sobre Boas Práticas, Artigo no estilo Solução Completa 04 - UML e Java na prática [ John Soldera ] Conteúdo sobre Boas Práticas, Artigo no estilo Solução Completa 13 - Refatorando código com padrões de projeto [ Gabriel Feitosa ] Conteúdo sobre Boas Práticas, Artigo no estilo Solução Completa 21 - Aprenda a utilizar o Spring Web Flow [ Alessandro Jatobá ] artefatos estes que visam espe- programa é dividir a aplicação em três níveis: camada cificar características importantes do software durante a fase de de apresentação. como o dia. unidades. Através de exemplos este artigo abordará como converter alguns Como um dos seus diferenciais. com o intuito de ilustrar o processo de co. o banco de dados. unidades de medida problema do mundo real é estudado e a solução proposta e pedidos. camada de negócios e camada de análise. o cadastro de fornecedores. Por último. Ao longo desse es- características dos sistemas de informação. obtidos diagramas padronizados para modelar as mais variadas durante o projeto de software. a tecnologia de simples e direta. projeto. implementação e testes. a momento em que são definidos a arquitetura do sistema. diagrama controle de estoque. e os mesmos serão convertidos. onde Dito isso. Tidas como fundamentais. uso e de classes. Com isso em mente. oferece um conjunto de dos principais diagramas da linguagem de modelagem UML. o diagrama de casos de uso e o diagrama diretamente a qualidade do produto. passo a passo. ferramentas como o JUnit. com o diagrama de classes. Porém. ocorre a fase de teste. a lingua- conversão dos diagramas da UML para código-fonte é gem de programação utilizada. cada funcionalidade do sistema é testada. 4 Copyright . mais especificamente os diagramas de casos de de sequência. Além disso. o ciclo de desenvolvimento envolve quatro A aplicação exemplo desse artigo tem o objetivo de realizar o grandes etapas: análise. Pelo fato da linguagem Java ser orientada a objetos. de classes. produtos e pedidos. Através deles é possível especificar o que usuário É durante a análise que o analista investiga e descobre pode fazer no sistema. conseguimos informar a ordem em que os objetos se comunicam para realizar as operações descritas nos casos de uso. É nessa fase que o problema. de sequência. Em seguida. com o auxílio de forma que o código-fonte seja organizado em camadas. entre outros. para não tornar o artigo muito longo. O conhecimento sobre estes delar as funcionalidades que o sistema fornecerá ao conceitos é algo fundamental à caixa de ferramentas de todo desen- usuário. Saiba que a fase de teste dificação a partir de diagramas UML. atributos e métodos. dados. tudo será analisada a documentação em UML de uma aplicação de grama de casos de uso. a criação de classes. uma sintaxe simplificada quando comparada com outras na fase de implementação. controle de estoque de um supermercado. e através do diagrama evoluir e manter. a seguir será apresentado o sistemas hoje em dia. uma aplicação pode ser executada desde o início do projeto. em código Java.UML e Java na prática UML e Java na prática Aprenda nesse artigo o que é UML e como desenvolver uma aplicação simples a partir dos diagramas de casos de uso e de classes A Fique por dentro linguagem de modelagem UML (Unified Mode- ling Language) é uma das linguagens de mode- lagem de software mais utilizadas no mundo. essa linguagem apresenta interface gráfica e a adoção de padrões de projeto. Lembre-se que uma abordagem desenvolvimento de uma aplicação exemplo a partir de alguns simplificada para organizar o código-fonte de um diagramas da linguagem UML. vamos é descrita através de modelos que sejam capazes de guiar focar apenas na implementação de algumas funcionalidades: o projeto do software. fornecedores. solução adotada para a construção da maioria dos Com base no conteúdo exposto. A linguagem UML também atua na etapa de projeto do software. pode-se definir as volvedor que tem como meta códigos mais fáceis de compreender. através da criação básica de controle de estoque será desenvolvida de de casos de testes integrados ao código-fonte. Todos os direitos reservados para DevMedia . produtos.Proibido copiar ou distribuir. entidades e seus relacionamentos. pular uma dessas etapas vamos modelar esta solução utilizando dois dos diagramas mais pode acarretar imprecisões. diagrama de classes. retrabalho e prejudicar conhecidos da UML. neste caso. o projeto de software é interpretado opções. Como ocorre normalmente em qualquer projeto de Aplicação exemplo software. para Através do diagrama de casos de uso é possível mo. o que facilita o processo de desenvolvimento e transformado em código na linguagem escolhida usando os de software. bem como as entidades do contexto do como funciona o sistema em questão. padrões especificados. editarFornecedor(). cada entidade deve conter apenas os atributos e métodos a ela relacionados. Note que através dos casos de uso já estabelecemos uma divisão para o sistema. especificamos ainda os diagramas Cadastro de Produto e Cadastro de Pedido (vide Figuras 3 e 4). ItemPedido e Produto. Além disso. foram especificados o criarFornecedor(). vejamos. são descritas as iterações que o usuário do sistema terá com a enti. na Figura 1. atributos. A Figura 2 apresenta outro caso de uso. métodos e relacionamentos de um sistema de forma visual. Caso de Uso Cadastro de Unidade Diagrama de Classes É através da criação de classes que a informação gerenciada pelo sistema é organizada em entidades separadas. respeitando sempre as diferenças de cada tipo de relacionamento. Note que o usuário deve ter acesso a quatro funcionalidades relacionadas à entidade Fornecedor: criação. Figura 1. Caso de Uso Cadastro de Fornecedor dade “unidade”. métodos e relacionamentos. Esta mesma lógi- ca se aplica às demais entidades. para que o software tenha um código com boa legibilidade e fácil manu- tenção. Sabendo disso. são definidos os relacionamentos entre essas classes. excluir e consultar unidades de medida. Casos de Uso Este diagrama descreve o que o usuário pode fazer. que serão usadas no cadastro de produtos – como será mostrado mais à frente. Assim. que. de forma que o usuário possa modificar cada parte do sistema separadamente. Nele. A partir dele o desenvolvedor terá um “mapa” do que implementar. Unidade. edição. como verificado. como veremos a seguir. A Figura 5 apresenta o Figura 3. seguem a mesma tendência apresentada pelos outros exemplos. Caso de Uso Cadastro de Produto diagrama de classes da aplicação exemplo. deve ser possível criar. Com esta ligação estamos indicando que um fornecedor pode ter zero ou muitos pedidos. de modo semelhante ao exemplo anterior. Ao analisar a entidade Fornecedor. exclusão e listagem. note que ele se relacionada com a entidade Pedido. Como exem- plo. os diagramas subsequentes na análise consideram as informações levantadas e modelam outras características. Encerrando a modelagem dos casos de uso. endereço. Figura 2. Como métodos. Ademais. o primeiro caso de uso da aplicação em desenvolvimento: Cadastro de Fornecedor. editar. Pedido. telefone e nome. de nome Cadastro de Unidade. Note que organizamos os dados da aplicação em cinco entidades: Fornecedor. Figura 4. Todos os direitos reservados para DevMedia 5 . Com o auxílio destes. O diagrama de classes se encaixa exatamente nesse contexto e nada mais é do que uma forma de representar as classes/interfa- ces. consultarFornecedor() e consultarFornecedores(). A partir disso. especificamos seus atributos.Espera-se que com o conteúdo o exposto o leitor consiga desen- volver as demais opções. verificamos que ele tem os atributos codigoFornecedor. excluirFornecedor(). para estabelecer o funcionamento do sistema e também para compor entidades mais complexas. o que facilita o trabalho de implementação e reduz o risco de criar códigos desnecessários. por exemplo.Proibido copiar ou distribuir. Caso de Uso Cadastro de Pedidos Copyright . que contém os atributos de cada entidade. uma das primeiras coisas a serem defini- patterns para facilitar e organizar a implementação do software. onde os diagramas obtidos anteriormente dados que pode ser enviado entre camadas distintas do software. um modelo pois existe uma tendência das classes originais conterem muita ER (Entidade Relacionamento) pode ser a única documentação informação pertencente a diferentes camadas da aplicação. de software. Durante a fase de projeto são Uma vez que se tenha evoluído na especificação do diagrama produzidos documentos e diagramas semelhantes aos da fase de classes da fase de projeto. de vida do software. usuário ou em decorrência de falhas no software. e uma classe DTO. o disponível no sistema. a fim de barrar na camada de persistência a repercussão de even- rada em duas: uma classe DAO. são convertidos em documentos ou outros diagramas de forma que seja mais fácil ao programador se basear neles para realizar Criação do Banco de Dados o desenvolvimento do software. porém tal informação sofre um detalhamento maior tabelas no banco de dados. Dentre elas. que é amplamente empregado em Java para e robusto é criar no banco de dados todas as verificações neces- organizar o software em camada de apresentação. Diagrama de Classes 6 Copyright . que contém os métodos de acesso a tuais falhas que possam ocorrer nas outras camadas. das é o banco de dados. de controle. em camadas. essa estratégia não é adequada. Concluída a fase de análise. além de centralizar todo o conhecimento do sistema Hoje já existem diversas formas de se organizar um software sobre as poucas pessoas envolvidas no processo de análise. pode-se partir para a criação das de análise. chaves estrangeiras e chaves únicas (campos que não se repetem) Em nosso exemplo. que abstrai e reduz o acoplamento do código com as tecnologias Portanto. de modelo e sárias sobre os dados para evitar o estado inconsistente da base. Entretanto. Todos os direitos reservados para DevMedia . opção que leva a uma divisão das classes em uma estrutura falta de validações de dados de formulários. como bugs ou ject. comumente. outro padrão bastante adotado é o Data Access Ob. cada classe presente na Figura 5 será refato. utilizadas para acesso a dados. é importante criar corretamente as chaves primárias. que causa uma forte vinculação entre essas camadas e prejudica uma vez que antecipa e distorce o processo de desenvolvimento diretamente a manutenção e legibilidade do código. Além disso. elementos que serão responsáveis e os processos são expandidos. deve-se prosseguir para a fase de Em definição simples. um objeto DTO representa um objeto de projeto de software.Proibido copiar ou distribuir. o que pode acontecer devido ao mau uso do sistema por parte do Além deste. uma das mais conhecidas é o padrão Outro aspecto importante em um projeto de software eficiente Model-View-Controller. muitas vezes empregando-se de pela persistência dos objetos que forem criados durante o ciclo pseudocódigo para descrever procedimentos.UML e Java na prática Fase de Projeto de Software dados. é na fase de projeto que são especificados os design Em muitos projetos. Nestes casos. Figura 5. valorProduto float. 03. codigoItem int. os analistas geram a especificação Como visto nesse código. Na Listagem 2 é apresentada a primeira classe da camada de persistência. telefone varchar(15). import java. public DatabaseManager() throws SQLException. em um banco de dados a camada de persistência. 26. } create table Pedido( 23.Proibido copiar ou distribuir. Como parte da fase de projeto. codigoBarras varchar(20). statement = connection. private static final String DB_URL = “jdbc:mysql://localhost/Estoque”. valorPedido float. Listagem 2. USER. create table Produto( 11. return statement. 10. FOREIGN KEY (codigoProduto) REFERENCES Produto (codigoProduto) 38. statement = connection.forName(JDBC_DRIVER). codigoPedido int. onde as classes relacionadas a este requisito devem ser imple- mentadas. 22. com o intuito de manter MySQL. 28. codigoPedido int.Driver”. 14. create table Unidade( 04. codigoProduto int. public ResultSet executeQuery(String sql) throws SQLException { dataPedido date.prepareStatement(sql). UNIQUE KEY (sigla) 09. Todos os direitos reservados para DevMedia 7 . 27. PRIMARY KEY (codigoPedido). codigoProduto int. descricao varchar(100). 35. uma boa organização do código.createStatement(). statement. ele mesmo pode criar a dos campos e seus tipos usando os tipos de dados disponíveis base de dados se tiver conhecimento na área (e se a empresa não na especificação do MySQL. codigoFornecedor int. que se encarrega de escrever entre as tabelas. ). public PreparedStatement prepararStatament(String sql) throws SQLException { create table ItemPedido( 31. as tabelas e seus atributos. crie o pacote database. package database. 36. 17.*. Listagem 1.jdbc. 39.createStatement(). 33. 05.setAutoCommit(autocommit). através das chaves contar com DBAs em seu time) ou delegar a atividade a um admi. ClassNotFoundException { nomeProduto varchar(15). PRIMARY KEY (codigoUnidade). } descricao varchar(100). FOREIGN KEY (codigoUnidade) REFERENCES Unidade (codigoUnidade). a qual tem a função de es- create database Estoque.getConnection(DB_URL. Código da classe DatabaseManager. 32. PreparedStatement statement. private static final String JDBC_DRIVER = “com. 16. estoque float. estrangeiras (FOREIGN KEY) configuramos os relacionamentos nistrador de banco de dados (DBA). tabelecer a conexão com o banco de dados e executar algumas create table Fornecedor ( consultas SQL. } Copyright . Além disso. 37. connection = DriverManager. 06. Statement statement = null. o nome da base de dados exemplo será de cada tabela e de cada campo do banco de dados informando o “Estoque”. local estrangeiras e únicas. } FOREIGN KEY (codigoFornecedor) REFERENCES Fornecedor (codigoFornecedor) 29. Observe também que foram definidos os tamanhos tipo e o tamanho do mesmo. connection. UNIQUE KEY (descricao) 21. nome varchar(100). private Connection connection. statement. PRIMARY KEY (codigoFornecedor). 20. ). Script para criação do banco de dados da aplicação exemplo. private static final String PASSWORD = “password”.execute(sql). Statement statement = null. 08. Para isso.close(). valorItem float. 25. PRIMARY KEY (codigoItem). private static final String USER = “root”. } ). UNIQUE KEY (nomeProduto).mysql. 07. já considerando a especificação de chaves primárias. 13. os scripts de criação do banco e fazer as alterações. statement = connection. ). isto é. 18. endereco varchar(100). codigoFornecedor int. sigla varchar(10). DatabaseManager. Class. Além disso. 19.executeQuery(sql). public class DatabaseManager { codigoUnidade int. 12.sql. public void setAutoCommit(boolean autocommit) throws SQLException { FOREIGN KEY (codigoPedido) REFERENCES Pedido (codigoPedido). 30. 24. O script para criação do banco de dados da aplicação exemplo Camada de Persistência é mostrado na Listagem 1 e tem o objetivo de criar a base de Iniciaremos a implementação do nosso diagrama criando dados. return statement. codigoUnidade int. public void executeSQL(String sql) throws SQLException { PRIMARY KEY (codigoProduto). UNIQUE KEY (nome) 02. 01. ). 34. PASSWORD). } quantidade float. 15. + “where codigoFornecedor = ?”.Proibido copiar ou distribuir. public static String update = “UPDATE Unidade SET “ + pode ser verificado na Listagem 3.” + 11.?)”.” + O código-fonte apresentado nessa listagem contém os comandos 11. artefatos que correspon- De forma semelhante.?)”. public class UnidadeSQL { 04.” + a senha da base. delete (linha 16) e select (linhas 21). package database. 20. + “where codigoUnidade = ?”. 06. Observe 18. + “where codigoUnidade = ?”. e terminar com setAutoCommit(true). O código-fonte destas pode é apresentado na Listagem 5 e para manter as boas práticas da ser verificado no arquivo disponibilizado para download nesta organização de pacotes. public class FornecedorSQL { consiga se conectar à base. e o método prepa. public static String select = “select * from Fornecedor “ criar transações. “descricao = ? “ + SQL voltados para as operações básicas de cadastro de fornece. endereco. 13. pode-se partir para a telefone e nome (vide linhas 4 a 7).?. 19. para que a aplicação 02. o driver de acesso é carregado na linha 6. 13.?. executados prontamente. dos SQL para o cadastro de unidades. Comecemos a implementação. exclusão e consulta de registros de cada 07. as regras de negócio da aplicação. Por fim. SQL enviados através da conexão com o banco de dados não sejam 01. dentre construtor default (linhas 9 a 10). criado para que seja possível preparar comandos 17. + “ values (?. pode ser baixado do site do MySQL. 15. O mesmo vale FornecedorDto.” + 12. banco no classpath da aplicação. 17. “telefone = ?. O seu código produtos. “WHERE codigoFornecedor = ?”. “codigoFornecedor = ?. o que efetiva todos os SQLs pendentes na conexão. ou seja. public static String update = “UPDATE Fornecedor SET “ + o nome do banco). endereco. como demonstram as instruções de insert (linha 5). essa classe deve ser implementada de forma que cada objeto contenha todos os dados relativos a um forne- Camada de Negócio cedor. + “where codigoFornecedor = ?”. Na 08. 15. um melhor desempenho (vide linhas 30 a 34). “codigoUnidade = ?. também conhecido 05.dto.UML e Java na prática Para que DatabaseManager funcione corretamente. Para tanto. linha 7. não é necessário explicar o seu código. dados descrita na Listagem 1. O primeiro exemplo disso 09. rogações. update (linha 9). “sigla = ?. deve-se adicionar o conector de acesso ao 04. public static String selectAll = “select * from Fornecedor”. 22. descricao) “ SQL de criação. qualquer comando SQL (vide linhas 17 a 28). Como verificado. 10. 08. ainda que existem dois comandos select: um para consultar um 20. “endereco = ?. edição. 03. responsáveis por executar diretamente 14. “ + Nesta classe também foram implementados os métodos execu. telefone. public static String selectAll = “select * from Unidade”. que permite 21. SQL que são executados com frequência mais alta e assim garantir 18. + “ values (?. Para definir o valor de cada 8 Copyright . Código da classe FornecedorSQL. basta iniciar a transação com setAutoCommit(false). 19. 02. local onde devemos implementar. + “(codigoUnidade. nome) “ 07. Note que para 14. dem a objetos de transmissão de dados e objetos de acesso a dados. que é responsável por conter todas as regras de para as classes que implementam as operações relacionadas a negócio relacionadas ao cadastro de fornecedores. e nas linhas 8 e 9 são informados o usuário e 10. public static String delete = “delete from Fornecedor “ rarStatement(). edição. o que envolve os atributos codigoFornecedor. Essa classe também contém o camada de negócios. public static String delete = “delete from Unidade “ especificar os parâmetros de cada comando são utilizadas inter- 16. entidade em uma classe específica. dores a serem usados em PreparedStatements.?. “nome = ? “ + teSQL() e executeQuery(). tem-se o método setAutoCommit(). ter o banco de dados MySQL instalado e em execução com a base de 01. na Listagem 4 são apresentados os coman. Este conector. public static String insert = “insert into Fornecedor “ como driver JDBC. 23. Visto que optamos por usar PreparedStatements para otimizar a 05. 12. sigla. é necessário Listagem 3. “WHERE codigoUnidade = ?”. Concluída a camada de persistência. 03. crie-a dentre do pacote negocio. o que faz com que os próximos comandos Listagem 4. public static String insert = “insert into Unidade “ eficiência da aplicação e do banco de dados. que possibilita criar um objeto outras coisas. fornecedores (linha 19). pedidos e itens pedidos. } Uma melhoria que pode ser realizada ao esquema apresentado é adicionar o comando LIMIT nos SQLs de consulta. Código da classe UnidadeSQL. então. 16. a fim de evitar o alto uso de memória no caso de as tabelas conterem um De acordo com os padrões selecionados na fase de projeto. Na Listagem 2. package database. pela classe é o mesmo. executar conjuntos de comandos SQL 22. public static String select = “select * from Unidade “ fornecedor pelo código (linha 21) e outro para consultar todos os 21. Como o padrão de consulta respectivamente. esta número muito grande de registros. é declarada a URL de acesso ao banco (repare no sufixo 09. Todos os direitos reservados para DevMedia . camada será dividida em DTOs e DAOs. } de forma atômica. A partir disso. + “(codigoFornecedor. deixaremos os scripts 06. sem informar os valores dos campos. telefone = telefone. } 24. veniente de um relacionamento entre as classes ProdutoDto e Uni- tatement para cada SQL definido em UnidadeSQL. não será exibido. return telefone. 18. o código da unidade é obtido através da à camada de persistência. pode ser utilizado exclusão e consulta são executados mais rapidamente. public void setNome(String nome) { 21. 22. 41. tatement(). 10. public String toString() { 36. String nome. além dos campos es. excluirUnidade() de tipo FornecedorDto. return nome. Essa classe funciona de forma editar. } 46. this. classe. da classe DatabaseManager. public String getNome() { 17. um raciocínio seme.nome = nome. unidade (do tipo UnidadeDto) é diferente. possui o campo fornecedor.codigoFornecedor = codigoFornecedor. por causa do relacionamento da classe e consultarUnidade() recebem um DTO como parâmetro. this. Código da classe FornecedorDto. public FornecedorDto() { 33. } 19. 29. Este retorna uma representação na forma de String do objeto e Os PreparedStatements declarados em UnidadeDao são inicia- será usado na camada de apresentação para criar uma descrição lizados no construtor através da chamada ao método prepararS- curta de um fornecedor. os métodos editarUnidade(). SQLs caso seja criada uma nova instância de UnidadeDao. 02. return endereco. os DAOs acessam a camada de persistência deDao e. pois o banco o getter correspondente.endereco = endereco. 06. Este ProdutoDto é criada uma referência para UnidadeDto. SQLs prontos no banco de dados para execução quando a aplicação plementar os DTOs das unidades de medida. 16. pedidos estiver rodando. 43. return codigoFornecedor. de forma recebe UnidadeDto como parâmetro. public int getCodigoFornecedor() { 40. } 42. é apresentado nas Listagens 8 e 9. 30. derivados dos relacionamentos de Uma exceção é o método consultarTodasUnidades(). de dados os mantém preparados em memória. ainda. o qual. public String getEndereco() { campo podem ser utilizados os respectivos setters. } 34. 45. Sendo assim. Um ganho importante com isso é que chamada ao método getCodigoUnidade() do objeto unidade. executar SQLs para inserir. definidos nesta através de PreparedStatements os scripts SQL de inserção. 08. this. public void setEndereco(String endereco) { 05. 25. public void setCodigoFornecedor(int codigoFornecedor) { 44. Para tanto. deixando os mesmos Em seguida. Este define objetos que encapsulam o código de acesso ao banco O código de FornecedorDao segue a mesma proposta de Unida- de dados.dto. Todos os direitos reservados para DevMedia 9 . edição. que a inicialização dos mesmos acontece no construtor. 01. 32. 12. os parâmetros a cada vez que são chamados. pertencente dadeDto. em Nas linhas 29 a 39 é declarado o método criarUnidade(). 20. 14. } 15. this. entre outras funções. porém o tratamento do seu campo Listagens 6 e 7 é apresentado o código da classe UnidadeDao. portanto. } 38. 26. return codigoFornecedor + “ . atributos produto e pedido. Listagem 5. ali- Pedido com Fornecedor. 31. recebe parâmetros por ser responsável por consultar e retornar Outro padrão de projeto usado na aplicação exemplo é o DAO. 37. } 11. uma vez que ele é pro- Nas linhas 13 a 17 dessa classe são declarados um PreparedS. Como existe uma relação entre as classes Produto e Unidade.Proibido copiar ou distribuir. De pecificados no diagrama de classes. classes semelhantes devem ser criadas para im. String telefone. Assim não será preciso construir novamente os e itens pedidos. public String getTelefone() { 09. alterando apenas Outro método presente na classe FornecedorDto é o toString().“ + nome. que não ItemPedido com Produto e Pedido. int codigoFornecedor. parâmetros no PreparedStatement insert e executa o SQL para O mesmo ocorre em PedidoDto. todos os registros da tabela Unidade. forma análoga. excluir ou consultar registros. public class FornecedorDto { 27. produtos. a partir deste define os que cada produto tenha uma unidade de medida. public void setTelefone(String telefone) { 13. } 03. sinalizando um pedido de compra. } 23. String endereco. conforme indicado no diagrama de classes (vide Figura 5). Copyright . E para recuperar o valor de um campo. 04. criar uma nova unidade de medida no banco de dados. 28. Já o código de ProdutoDao para obter a conexão com o banco. 47. mentam o PreparedStatement com os valores por ele esperados Concluindo a implementação dos DTOs. package negocio. que declara os banco de dados. } 07. Note. 35. Nas análoga aos demais DAOs. 39. e executam o SQL correspondente para aplicar as alterações no lhante pode ser verificado em ItemPedidoDto. return unidade.getDescricao()). ArrayList<UnidadeDto> lista = new ArrayList<UnidadeDto>().PreparedStatement. ResultSet rs = select.dto. 44. consequentemente explorar novos conceitos. } 22.prepararStatament(UnidadeSQL. unidade. } 79. try { 12. unidade. 32. private PreparedStatement update. try { 64. a necessidade de escrita do código SQL. delete. UnidadeDto unidade = new UnidadeDto(). update. 04. public UnidadeDto consultarUnidade(int codigoUnidade) { 10 Copyright . 46. } 28. 94. pois também são buscados os dados outras coisas. 89.getSigla()). que foram omitidos por questão de espaço.update). nas consultas. Todos os direitos reservados para DevMedia . catch (SQLException e) { 29. da unidade de medida do mesmo. 41.ResultSet. unidade. } 95. explorando frameworks Java criados exatamente com trutor. 07.getSigla()). 36. return null. 56. 48. } 81. public void editarUnidade(UnidadeDto unidade){ 11. 26. } 08. Código da classe UnidadeDao – Parte 2.getString(“sigla”)). 55. 20. 43. Um bom exemplo é o Hibernate. Dito isso. e.delete). unidade. } 05. e. catch (SQLException e) { 19. try { 61. 45. 98. } 82. } 18. 13. 78.UML e Java na prática Além disso. 97. unidade.getCodigoUnidade()). import java.dao.util. try { 85.setDescricao(rs.setCodigoUnidade(rs.sql. 38. select. return lista.sql. insert. Código da classe UnidadeDao – Parte 1.DatabaseManager.Proibido copiar ou distribuir.executeQuery(). 33.UnidadeDto.getCodigoUnidade()).selectAll).prepararStatament(UnidadeSQL.printStackTrace(). } Listagem 7. unidade. import negocio. temos ainda os DAOs PedidoDao e leitor pode buscar realizar essa refatoração em nosso exemplo e ItemPedidoDao.setInt (1. package negocio. 68. catch (SQLException e) { 96. update. lista. 65. que é consultado no tar o código relacionado ao acesso a dados de uma maneira mais banco de dados usando o DAO UnidadeDao informado no cons.setSigla(rs.executeUpdate(). 59. simples. update. insert. 49. unidade. delete = databaseManager.executeUpdate(). catch (SQLException e) { 76. if (rs. 30. dentre apenas aos dados do produto. update = databaseManager. 54. 52.setString(2. que abstrai. public void criarUnidade(UnidadeDto unidade){ 60. private PreparedStatement select.prepararStatament(UnidadeSQL. import java. 92.executeQuery().setString(3. public void excluirUnidade(UnidadeDto unidade){ 24. 14. 62. return null.setDescricao(rs.next()) { 67. UnidadeDto unidade = new UnidadeDto(). 69.setCodigoUnidade(rs. unidade. unidade. a partir de artigos já publicados nesta revista sobre esse tema. 90. public class UnidadeDao { 42. insert. 84.printStackTrace(). unidade. select = databaseManager. e. é criado também um UnidadeDto. } 99.ArrayList.setInt(1. } 09. unidade. é válido ressaltar que podemos implemen- criado. o Com código semelhante. 40.add(unidade). private PreparedStatement selectAll.executeUpdate(). } 73. import java. 27.getCodigoUnidade()).getInt(“codigoUnidade”)). private PreparedStatement insert.select).prepararStatament(UnidadeSQL. } 21. 71. 86. 57. e. 53. para cada objeto do tipo ProdutoDto Concluída essa etapa. insert = databaseManager.printStackTrace(). ResultSet rs = selectAll. e.setInt (1. import database.prepararStatament(UnidadeSQL. 77. public ArrayList<UnidadeDto> consultarTodasUnidades() { 83.getString(“sigla”)). unidade. 51.printStackTrace(). codigoUnidade).setSigla(rs. import java.next()) { 87.getDescricao()). 16. 63.sql. a informação consultada não se restringe esse intuito. 74. 39. return null. 72. 15.setInt (4. unidade.getInt(“codigoUnidade”)). delete. 66. while (rs. } 93. 91.printStackTrace().SQLException. update.getString(“descricao”)). catch (SQLException e) { 06. import database. 47. selectAll = databaseManager.setString(2.insert). 70. 101. } 100. Listagem 6. 03. } 58. 88. public UnidadeDao(DatabaseManager databaseManager) throws SQLException { 50. 34. update. unidade.getCodigoUnidade()). 10. } 75. 17. 37. Deste modo. 35.setString(3. 01. 23. insert. try { 25. } 31. 02.UnidadeSQL.getString(“descricao”)).setInt (1. 80. private PreparedStatement delete. 43. return lista. 07. } 05. insert.setValorProduto(rs.setValorProduto(rs. produto. ResultSet rs = select. 34. 42. 18. insert. return null.getUnidade().setNomeProduto(rs. ProdutoDto produto = new ProdutoDto().getString(“codigoBarras”)). 46. 25.DatabaseManager.UnidadeDto.setCodigoProduto(rs. UnidadeDao unidadeDao) throws SQLException { 55.dao. selectAll = databaseManager.setFloat (4.getCodigoProduto()). 22. 06. 41. 49. 20.prepararStatament(ProdutoSQL. e. 25. 49.getInt 51.getCodigoBarras()). 26. update. 22. produto. import java. 10.setInt (7.printStackTrace().getString(“nomeProduto”)). try { 30.getEstoque()). insert. try { 08.delete). 09.printStackTrace(). private static PreparedStatement select.update). 50.getFloat(“valorProduto”)). update. produto.Listagem 8. 50.getDescricao()). produto. produto. private static PreparedStatement insert. produto.setInt (7. 59. produto.setNomeProduto(rs. 17. produto. public ProdutoDao(DatabaseManager databaseManager.prepararStatament(ProdutoSQL. insert.selectAll).prepararStatament(ProdutoSQL. update. 30.executeQuery().getNomeProduto()). update.getFloat(“estoque”)).setEstoque(rs. 53. delete. 14. 62. 01. ProdutoDto produto = new ProdutoDto(). produto. update. } 31. 16. try { 03.insert). return null.setFloat (4. produto. insert. catch (SQLException e) { (“codigoUnidade”))). delete = databaseManager.setDescricao(rs.setCodigoProduto(rs.setString(2. 04. 44. insert. 48. codigoProduto). return null. produto.setString(3. insert. 09. 35. 27. 54. 36.setUnidade(unidadeDao.unidadeDao = unidadeDao. 48. public ProdutoDto consultarProduto(int codigoProduto) { 07.PreparedStatement. 05.sql. Listagem 9. catch (SQLException e) { 29. 47. } 33. while (rs.getEstoque()).getInt(“codigoUnidade”))). 44. package negocio. } 23.setString(2. } 16.setEstoque(rs. 19. 53.setFloat (6. update. 01. import java.executeUpdate().getUnidade(). 39. 02.getString(“descricao”)). public ArrayList<ProdutoDto> consultarTodosProdutos() { 39.next()) { 43. update. produto. import negocio.getValorProduto()).setInt (1. 31.executeUpdate(). 47.executeQuery(). import negocio.ResultSet. public void excluirProduto(ProdutoDto produto){ 29.setInt (1. } 21. private static PreparedStatement delete. 61. if (rs. produto. 60. lista. Todos os direitos reservados para DevMedia 11 .printStackTrace(). select = databaseManager. } 63.ArrayList. produto. e. 03.setInt(1. Código da classe ProdutoDao – Parte 1. private UnidadeDao unidadeDao. import database. 23. synchronized (this) { 57.getInt(“codigoProduto”)).prepararStatament(ProdutoSQL.ProdutoSQL. 42. 12.setInt (1.Proibido copiar ou distribuir. 06. 40. try { 19. produto. } 36. } 15. Código da classe ProdutoDao – Parte 2. update. } 32. } 04.dto. catch (SQLException e) { Copyright . produto. catch (SQLException e) { 13.dto.setString(5. } 28. 33.getCodigoProduto()).getCodigoProduto()). 17.executeUpdate(). 15. 08. e. this. public class ProdutoDao { 45.SQLException. e. public void editarProduto(ProdutoDto produto){ 18. produto. } 37.sql.getFloat(“valorProduto”)). produto. 38. private static PreparedStatement selectAll. produto. 35. try { 41. 40.util. produto. 21. produto.add(produto). update. 10. produto. private static PreparedStatement update.setCodigoBarras(rs.getDescricao()).setString(3. 58. produto. 52.setString(5. import database. 55. 24.getInt(“codigoProduto”)). } 56. 14.getCodigoUnidade()).consultarUnidade(rs. produto. produto.setUnidade(unidadeDao. produto. 46. return produto. delete. select.getFloat(“estoque”)).getValorProduto()). insert = databaseManager. 56. } 12. 20.setFloat (6. 37.setDescricao(rs. 24. public void criarProduto(ProdutoDto produto){ 02. } 26.prepararStatament(ProdutoSQL. import java.getString(“descricao”)). import java. 11. catch (SQLException e) { 34.select). produto. 45.consultarUnidade(rs.sql. ArrayList<ProdutoDto> lista = new ArrayList<ProdutoDto>().setCodigoBarras(rs. insert.getCodigoProduto()). 51.setInt (8. 13. produto.printStackTrace().getCodigoBarras()). e.getCodigoUnidade()).ProdutoDto. produto.getString(“codigoBarras”)).getNomeProduto()). 52. } 64. } 54. ResultSet rs = selectAll. update = databaseManager.next()) { 11. } 27.printStackTrace().getString(“nomeProduto”)). 32. 38. } 28. produto. a linguagem UML é uma poderosa ferramenta de modelagem de software e apresenta diversos diagramas que auxiliam as atividades de desenvolvimento. da comu- nicação entre os desenvolvedores. JavaFX ou. respectivamente. assim como uma melhora da legibilidade e manutenibilidade do código. a janela exposta na Figura 7 é apresentada – a qual contém todos os casos de uso relacionados a fornecedor (vide Figura 1) – oferecendo acesso às operações de criação. https://www. https://docs.UML e Java na prática Camada de Apresentação A camada de apresentação proposta para a aplicação exemplo foi implementada usando Swing. mas o código-fonte foi omitido. que permite o acesso a todos os casos de uso da aplicação de controle de estoque. outras tecnologias poderiam ter sido empregadas como. produtos e pedidos. Tela do cadastro de produtos Javadoc da plataforma Java SE 8. Todos os direitos reservados para DevMedia . Trabalha com Java há 12 anos e possui a certificação SCJP. edição e exclusão de fornecedo- res. criação. Ao selecionar a primeira opção. empresas que primam por qualidade e bons pro- jetos de software exigem dos desenvolvedores cada vez mais o domínio dos principais diagramas dessa linguagem de modela- gem. O mesmo vale para as telas exibidas nas Figuras 8. por exemplo. pois isso implica diretamente na boa conversão dos mesmos em código-fonte correto e eficiente. No entanto. sua adoção possibilita um aumento da qualidade da documen- tação produzida nas fases de análise e projeto.com/ Figura 10. Consequentemente.oracle.Proibido copiar ou distribuir.com/javase/8/docs/api/ Página oficial do Hibernate. considerando-se que a camada de apresentação se torne acessível via web. Tela do cadastro de fornecedores Diante disso.com Figura 8. mestre em Computação Aplicada pela Uni- sinos e doutor em Ciências da Computação pela UFRGS (Universidade Federal do Rio Grande do Sul). Tela principal da aplicação exemplo que viabilizam o acesso às funcionalidades de listagem. AWT. Figura 7. 9 e 10. ainda. Links: Figura 9. entre outros fatores. http://hibernate. Como verificado. tecnologias como JSP (JavaServer Pages) e JSF (JavaServer Faces). por não fazer parte do escopo deste artigo.mysql. Na Figura 6 temos a tela principal do software. edição e exclusão de unidades de medidas. Cadastro de Fornecedor. Tela do cadastro de pedidos 12 Copyright .org/ Página oficial do MySQL. Autor John Soldera johnsoldera@gmail. Tela do cadastro de unidades de medida É bacharel em Ciências da Computação pela UCS (Universidade de Caxias do Sul). Figura 6. As telas da aplicação serão mostradas nas imagens a seguir. de padrões as cidades medievais eram mais bonitas e harmônicas. como codificar de ção entre arquitetos e desenvolvedores ao viabilizar um vocabulário forma estruturada. por exemplo. encapsulamento Language”. será ainda mais alto sem aplicá-las. sobre como refatorar um projeto exemplo aplicando os padrões Prototype. O conceito da abstração. Com essas medidas o processo de por apresentar uma maneira prática para detecção de problemas de desenvolvimento tende a se tornar mais caro. sibilita focar no que é um objeto e qual comportamento ele terá mo inviável. por sua vez. padrões em construções futuras ou na melhoria das já existentes. se aplicadas corretamente. permitirão um comuns sejam compartilhadas entre diferentes classes. em que ele apresenta como utilizar e herança. cionalidades. de forma mais simples. problemas como código duplicado. evita-se que o Diante disso. receba novas fun. O conceito de herança. Em sistemas em que não houve essa preocupação a refatoração será um processo bastante complexo ou mes. como abstração. entre objetos e que uma mudança objetos e padrões de projeto. Para A utilização de padrões de projeto permite o desenvolvimento de manter o padrão alto é primordial evitar o uso de mé. aplicar técnicas que amenizem a pro. Além disso. explanará do desenvolvimento do software e de sua manutenção. ajudarão o profissional a produzir um visão geral sobre padrões de projeto e como eles são código de qualidade e a reduzir o esforço necessário no decorrer utilizados na linguagem Java. permitirá métodos e atributos podem ser reutilizados. um código limpo. isto é. como tentar modificá-lo. viabilizado pelos modificadores de acesso. este artigo dará uma tos de padrões de projeto. Além disso. entre outros indícios Já o encapsulamento consiste em adicionar segurança à aplica- que sinalizam a baixa qualidade. Es. é necessário escrever comum. Esses fundamentos da orientação a objetos. software crie uma interdependência excessiva. presente em projetos de software. Strategy e Adapter O desenvolvimento de software de qualidade é um processo que exige tempo e um elevado Fique por dentro esforço por parte da equipe do projeto.Proibido copiar ou distribuir. Ele constatou que por conta do emprego O paradigma da orientação a objetos estabelece fun. este artigo é útil tenção e evolução. Padrões de projeto ou Padrões GoF O conceito “padrão de projeto” surgiu com o arquiteto austríaco Fundamentos da orientação a objetos Christopher Alexander. damentos que influenciam diretamente a organização e O resultado dessa observação foi a publicação do livro “A Pattern qualidade do código. que normalmente dução de código ruim é essencial. em meados de 1970. assim como facilita a comunica- todos antiquados ou inapropriados. como a orientação a chamamos de alto acoplamento. algo código pensando também na sua facilidade de manu. utilizadas para alcançar possa gerar efeitos colaterais em todo o sistema. proporciona que estruturas sas técnicas. baixa coesão. evitando possíveis que o sistema seja estendido. Assim. junto com os concei- Com base no que foi apresentado. Em alguns casos chega ção. um alto nível de satisfação na produção do código. Com base nisso. e assim. amenizando possíveis problemas de interpretação. Em seguida. Copyright . mas o design no código e como refatorá-lo empregando boas práticas ao custo para corrigir os problemas e manter o software introduzir padrões de projeto ao ciclo de desenvolvimento. pois o código provavelmente apresentará antes mesmo de começar a ser implementado. código mais fácil de ser mantido. alto acoplamento.Refatorando código com padrões de projeto Veja neste artigo uma abordagem prática para melhorar a qualidade do código com os padrões Prototype. Isso porque através deste conceito haverá a separação entre a ser mais aconselhável criar um novo sistema do que aspectos externos e implementações internas de um objeto. flexível e testável. Strategy e Adapter. pos. Todos os direitos reservados para DevMedia 13 . ele fornece um objeto substituto (proxy) ao verdadeiro. Em outras palavras. pois cada aplicativo Java tem uma única instância dessa classe que permite interação entre o aplicativo e o ambiente em que é executado. Todos os direitos reservados para DevMedia . Encapsular o acesso a uma funcionalidade de um sistema ou módulo. Richard tos e representados. Controlar as chamadas a um objeto por meio de outro de mesma interface. Desacoplar uma abstração de sua implementação. estruturais e comportamentais.Graphics. esse proxy poderá interceptar as chamadas aos métodos originais e adicionar ações antes ou depois do seu uso.util. utilizam o método java. Padrões de projetos estruturais 14 Copyright . As classes que implementam a interface java. Proxy Assim. Compartilhar. a fim de manter sua Decorator estrutura intacta. os padrões dessa categoria estão padrões catalogados e que descrevem soluções para diversos relacionados com a estrutura dos objetos.Runtime é um exemplo Singleton de Singleton implementado pela JVM. ou seja.InputStream) e os adapta para caracteres (java. Porém. Isso ocorre devido ao encapsulamento do Helm. A Facade classe java.BufferedOutputStream. Um exemplo de aplicação real desse design pattern é a classe java.InputStreamReader recebe uma cadeia de bytes (java.List Composite implementa o padrão Composite para adicionar os objetos de uma coleção ao final da lista especificada. Tabela 1.getInstance() é uma Factory Method implementação da proposta definida pelo Factory Method. os A Tabela 1 apresenta os seis padrões criacionais e os seus autores ficaram conhecidos como a “A Gangue dos Quatro”. começaram a ter notoriedade na área da computação. A utilização desses padrões auxilia o sistema ser utilizado por Kent Beck e Ward Cunningham. Assim é possível reduzir o número de objetos criados.lang.Object. o termo começou a classe e objeto. sem alterar a sua estrutura.io. por exemplo. as que fazem acesso JDBC ao banco de dados. Por exemplo. a composição das classes e dos objetos e com o relacionamento como será visto a seguir. A classe java. Padrões de projeto Objetivo Prover uma interface para criar uma família de objetos relacionados ou dependentes sem especificar suas classes concretas. esse padrão cria uma classe decoradora que irá envolver a classe original e fornecer métodos adicionais para manipulá-la. o java.io. Esse padrão é facilmente encontrado Bridge nas bibliotecas de drivers como.Refatorando código com padrões de projeto Já no âmbito da Engenharia de Software. Em outras palavras. em meados de a ser independente de como seus objetos são criados. quando Erich Gamma. pois ele faz uso de cache interno.lang. de modo que um mesmo processo possa gerar diferentes Builder representações de forma transparente. pois ela recebe em seu constru- tor um objeto java. ou Gang objetivos. considerado aplicação e também pela ocultação do modo como essas classes a referência mais importante sobre o assunto.Reader). a fim de simplificar seu uso e fornecer uma interface mais amigável. de modo que ambas variem de maneira independente. classes com interfaces incompatíveis poderão trabalhar Adapter em conjunto. O livro está dividido em três categorias. por exemplo.lang. Encapsular a escolha da classe concreta a ser utilizada na criação de um determinado tipo de objeto. O método valueOf(long) da classe java. Foi daí que surgiu a nomenclatura “Padrões GoF”. pois ele encapsula a forma de criar um novo objeto concreto (Calendar). O método Calendar. como validar a restrição de segurança.Proibido copiar ou distribuir. O método addAll(Collection) de java. através da interface de adaptação. utilizada para executar comandos em sistemas operacionais. Ralph Johnson e John Vlissides publicaram o livro “Design conhecimento sobre as classes concretas que serão usadas pela Patterns – Elements of Reusable Object-Oriented Software”. de forma eficiente. por exemplo. objetos que são usados em grande quantidade. Permitir que funcionalidades sejam adicionadas a um objeto existente em tempo de execução. somente em 1995. Após isso. Um bom exemplo é a classe java. Ao todo são vinte e três Como o próprio nome diz. Agrupar objetos que fazem parte de uma relação parte-todo de forma a tratá-los sem distinção. Assim. a saber: padrões de Padrões estruturais criação. aumen- Flyweight tar o desempenho e amenizar o consumo da memória.clone() para criar cópias de si mesma.lang. entre eles.io.awt. Permitir a criação de um novo objeto através da cópia das propriedades de um objeto existente. Essa é a ideia do java.OutputStream e o “decora”. mas que possui propriedades idênticas à inicial.io.lang. é uma fachada que oferece métodos simples para as operações relacionadas aos gráficos. Tabela 2.Proxy.reflect. Eles se preocupam com problemas recorrentes durante o processo de desenvolvimento. ele usa uma instância de Prototype uma classe para criar uma nova. Separar o processo de construção de objetos complexos de sua representação.io. compos- 1980. descritos na Tabela 2. deixando o desenvolvedor livre desta criação de objetos e podem ser divididos em duas categorias: preocupação.Cloneable. of Four (GoF). Padrões de projetos criacionais Padrões de projeto Objetivo Converter a interface de uma classe em outra que possa ser utilizada por clientes. é facilitar o Padrões de criação design do sistema identificando maneiras de realizar o relaciona- Os padrões de criação têm a função de abstrair o processo de mento entre as entidades. O objetivo destes padrões.ProcessBuilder.Long é um ótimo exemplo de implementa- ção desse padrão. os padrões de projeto são criadas e formadas. Garantir que uma classe tenha somente uma instância e fornecer um ponto global de acesso à mesma. O Abstract Window Abstract Factory Toolkit (AWT) utiliza esse padrão para fornecer um conjunto de classes independentes de plataforma específicas para operações gráficas.lang. Definir um objeto que encapsula a forma como um conjunto de objetos interage. As implementações de java. Alterar o comportamento de um determinado objeto de acordo com o estado no qual ele se encontra.Timer são exemplos de implementação desse design pattern.lifecycle. pois internamente faz uso de um long para armazenar o valor da data. por exemplo. entre os objetos distribuindo as responsabilidades e definindo a Diante disso. Capturar e externalizar o estado interno de um objeto. Strategy e Adapter. A refatoração aplicando os padrões Prototype. Padrões de projeto Objetivo Promover o desacoplamento entre o objeto solicitante e o solicitado. registradas ou desfeitas. O jogo consiste em uma batalha onde os robôs podem se movi- Para atender esse requisito. preciso que o sistema seja reconfigurado com os novos valores. Na verdade. Um exemplo Chain of responsibility de aplicação desse padrão é o tratamento de exceções. Dito isto.io. é um exemplo prático da aplicação desse padrão. que. eles auxiliam a comunicação mais justa. de modo que ele possa ser restaurado posterior- Memento mente. Encapsular uma solicitação como objeto. sem violar o encapsulamento. A partir de agora esses pro- ção: imagine um sistema que possui suas configurações em um fissionais estarão encarregados de melhorá-lo. java. sempre que o arquivo for alterado o sistema ximo ele deve realizar uma série de comportamentos para atingir será notificado para atualizar seu comportamento de acordo com o oponente ou fugir. Isto é.util. Strategy e Adapter evolução do código. Essa regra foi definida para tornar a partida as entidades se comportam. O método compare() da interface java.OutputStream. muito utilizado para ordenação de listas. A classe java. a execução do al- Visitor goritmo pode variar de acordo com a classe visitante. como Estes padrões. mentar em um tabuleiro e ao detectar que há um oponente pró- plementado.InputStream. permite notificar o início e o fim de cada fase do ciclo de uma requisição. os objetos receptores serão encadeados e transmitidos à solicitação através de uma cadeia até que um objeto o trate. para acompanhar a Aplicando os padrões Prototype. pois há relatos que o arquivo de texto e todas as vezes que esse arquivo for alterado é jogo é lento quando há muitos robôs participando de uma partida.Action utilizam esse padrão. no qual uma exceção recursivamente escala a pilha de métodos até encontrar um capaz de tratá-la.text. optaram por criar uma partida com apenas Padrão de projeto não é código pronto para ser reaproveitado três robôs.ElementVisitor. Padrões de projetos comportamentais Copyright .Date é um exemplo para esse padrão. Tabela 3. Dessa forma. Todas as implementações de java.io. sem que a estrutura interna dessa coleção Iterator seja exposta. o formato de exibição de uma data. descritos na Tabela 3. Em seguida.model.faces. ou seja. uma característica importante as novas especificações. Definir um mecanismo eficiente para reagir às alterações realizadas em determinados objetos. A interface javax.element. Assim. As subclasses de java. O Mediator promove o acoplamento fraco ao evitar Mediator que os objetos se refiram uns aos outros explicitamente e possibilita variar suas interações independentemente.Comparator. State LifeCycle. ele é um modelo Na Listagem 1 é apresentada a classe Jogo. usa a representação para compreender sentenças dessa linguagem. java. Fornecer um modo eficiente para percorrer sequencialmente os elementos de uma coleção. Assim. A classe javax. tem a função de definir uma representação para sua gramática Interpreter juntamente com um interpretador.io.util. a fim de simplificar a execução encadeada de comandos. Assim.Reader e java. Definir a ordem na qual determinados passos devem ser realizados na resolução de um problema e possibilitar que eles possam ser exe- Template Method cutados de formas diferentes de acordo com a situação. é que todos os robôs devem possuir os mesmos atributos.swing. Strategy propicia que o algoritmo varie inde- Strategy pendente dos clientes que o utilizam. Todos os métodos não abstratos de java. e detectaram alguns pontos que podem ser melhorados com a adoção de padrões de projetos. o comportamento será o de construir os elementos da tela.util.util.Padrões comportamentais de agora será apresentado um exemplo de um jogo de robôs com Os padrões comportamentais fornecem estratégias consolidadas problemas arquiteturais que podem ser solucionados através de para modelar a maneira como os objetos colaboram entre si. Permitir que uma classe visitante mude o algoritmo de execução de outra sem a necessidade de alterá-la. Todos os direitos reservados para DevMedia 15 . no desenvolvimento de software. tratam da forma como força e velocidade. partir disso.io.Proibido copiar ou distribuir.faces. Todos os métodos scheduleXXX() da classe java. que opera em conjunto com o objeto Element do mesmo pacote. Definir uma família de algoritmos. se a fase for para restaurar a cama de visão (Restore view). por exemplo. por exemplo. as operações podem ser enfi- Command leiradas.lang.lang.PhaseListe- Observer ner. artefato que repre- abstrato para resolver determinado problema.Iterator fazem uso desse padrão. vendido para outra que tem em sua equipe de desenvolvimento Vejamos um exemplo para facilitar a compreensão dessa defini. Além disso.event. por sua vez. encapsular cada uma delas e torná-las intercambiáveis. viabilizam a redução do acoplamento e tornam o Imagine que esse jogo era implementado por uma empresa e foi código mais preparado para receber novas funções/extensões. tem dependência do estado do ciclo de vida do JSF. o padrão de projeto Observer foi im. fazer validações nos componentes e salvar a view no FacesContext. profissionais com bastante experiência.Writer implementam o Template Method. dando oportunidade a diversos objetos de tratar a solicitação.Runnable e javax. a partir senta o tabuleiro onde os robôs realizam as batalhas. Um exemplo é o javax. os desenvolvedores fizeram uma análise no código comunicação interna. Dada uma linguagem.Format fazem uso do padrão Interpreter. MovimentoEnum. private String nome. apresenta * Implementação da estratégia de movimento aleatório. mas que apesar de aparen. ALEATORIO } Listagem 1. * } * @param acao A ação de movimentação.nome = nome. public class Jogo { // Código com os demais atributos suprimido public static void main(String[] args) { //Cria uma instância de robô public Robo() { Robo rambo = new Robo(). soluções para resolver problemas padrão os robôs poderão ser clonados. //Solicita que o robô se movimente de forma defensiva /** chuckNorris. } //Cria outra instância de robô /** Robo chuckNorris = new Robo(). * Resgata os dados de um banco de dados para inicializar o robô.} Robo bigHero = new Robo(). Ademais. DEFENSIVO. isto é. pois já que os robôs são todos iguais (exceto pelo tem acesso ao código fonte com a implementação real da classe.Refatorando código com padrões de projeto A intenção da equipe. nova instância para cada um.ALEATORIO).equals(acao)) { necessárias para instanciar um robô. temente benéficas. Código da classe Jogo que simula o tabuleiro de batalha dos robôs.execute() new MovimentoAleatorio(). como força e velocidade. um trecho de código que invoca o método MovimentoAleatorio. rambo. // Algoritmo para movimentação agressiva trutor. */ public class MovimentoAleatorio { execute().. repare que ele possui com a aplicação do padrão de projeto Prototype. bigHero. A primeira delas. a movimentação do robô. no método mover().mover(Robo. jogo a fim de identificar. * Todos os robôs são iguais.execute(). esse } método também possui a implementação dos algoritmos referen. Todos os direitos reservados para DevMedia . static enum MovimentoEnum { AGRESSIVO. //Solicita que o robô se movimente de forma agressiva } rambo. Para isso. por sua vez. na verdade prejudicam a manutenibilidade.setNome(“Rambo”). inicializar(). note que há uma chamada ao método inicializar().. em vez de ser criada uma aplicando práticas muito utilizadas. uma defesa ou movimentos aleatórios! bigHero.mover(Robo. //Solicita que o robô se movimente de forma aleatória * Pode ser um ataque. nome) e o custo para criar um robô é elevado. este anti-pattern pode ser resolvido Ao analisar o código das Listagens 1. respon.AGRESSIVO). flexibilidade.MovimentoEnum. reuso. Em seu cons. Através desse uma série de anti-patterns. // O algoritmo de movimentação aleatória é implementado O método mover(). de acesso ao banco de dados. exceto o nome! */ //Cria mais uma instância de robô private void inicializar() {. a equipe de desenvolvimento não Robo é criado. 2 e 3. o método execute() implementa o algoritmo que realiza a movimentação aleatória de um robô.equals(acao)) { // Algoritmo para movimentação defensiva sável por acessar um banco de dados e resgatar as informações } else if (MovimentoEnum. robô. } tes ao movimento solicitado. com mais facilidade. public void setNome(String string) { this.mover(Robo.equals(acao)) { Já na Listagem 2. Por se tratar O primeiro problema está relacionado à forma como o objeto de uma biblioteca de terceiros. inclusive.ALEATORIO. chuckNorris.AGRESSIVO.setNome(“Big Hero 6”). com isso. Perceba também que somente a lógica de movimento aleatório /** (MovimentoEnum. acabou de ser citada: dividir para conquistar. devido à necessidade Portanto não é possível realizar modificações.DEFENSIVO.Proibido copiar ou distribuir.setNome(“Chuck Norris”). A implementação da classe Robo.DEFENSIVO).ALEATORIO). foi isolar pequenos trechos do Listagem 2. ele recebe como parâmetro } qual tipo de movimento o robô deverá executar. Outro ponto questionável está relacionado ao método mover(). Note que para cada movimento há Listagem 3. entre outros. } */ public void mover(MovimentoEnum acao) { if (MovimentoEnum. Classe responsável pelo algoritmo de movimentação aleatório do uma lógica implementada na estrutura condicional if/else. temos o código da classe Robo. * Executa o comando de movimentação. } A Listagem 3 apresenta o código da classe MovimentoAleatorio e como verificado. Note que ele acopla todo o conhecimento de como um robô se 16 Copyright . Os demais algoritmos de movimentação não foram //Algoritmo para executar a movimentação aleatória } analisados e por isso o código dos mesmos não foi exibido. tem a responsabilidade de realizar // por terceiros através do método MovimentoAleatorio.MovimentoEnum. problemas que pos- public class Robo { sam ser sanados com boas práticas. Isso ocorre devido ao uso de uma biblioteca de terceiros que já implementava um algoritmo de movimentação aleatória public void execute() { para um robô. } else if (MovimentoEnum. /** * Resgata os dados de um servidor para inicializar o robô. Com um if na estrutura do método mover. Ao aplicar esse padrão não é necessário carregar essas infor. public void setNome(String string) { this. código semelhante ao apresentado na Listagem 4. Listagem 4. Todos os direitos reservados para DevMedia 17 . A primeira Por fim.clone(). esse pattern pode trazer ganhos significativos de } performance para uma aplicação.Proibido copiar ou distribuir. } Uma aplicação para esse padrão pode ser verificada na manipu. * A estrutura do padrão Prototype pode ser vista no diagrama de * @param acao A ação de movimentação. DEFENSIVA. private String nome. Diagrama de classe do padrão Prototype – Fonte: http://www. public void mover(MovimentoEnum acao) { if (MovimentoEnum. A partir /** * Executa o comando de movimentação. com diferentes cópias.DEFENSIVA. } } Figura 1. Aplicando o padrão Prototype public class Robo implements Cloneable { O padrão de projeto Prototype tem como propósito criar novos static enum MovimentoEnum { objetos a partir de uma instância protótipo. */ classes exposto na Figura 1. o objeto que AGRESSIVA. Lembre-se que Adapter permite cópia de si mesma. A solução para minimizar a implementação do Prototype o acesso à base de dados será rea- o acoplamento e facilitar o reuso do código está na aplicação do lizado somente para a criação da instância protótipo do Robo. exceto o nome! mações financeiras todas as vezes que um novo modelo for */ simulado. ela não pode ser modificada pela equipe de desenvol- vimento do jogo.nome = nome. Além disso. A outra mudança é a implementação do mé- que estruturas diferentes possam trabalhar juntas através de todo clone(). dificulta a criação do objeto Robo (vide Listagem 2) tem um processamento manutenção do código. simular diferentes modelos matemáticos utilizando } dados financeiros de um país que. * Todos os robôs são iguais. Isso ocorre devido à necessidade de de criar um novo tipo de movimento será necessário adicionar acessar a base de dados sempre que um robô é instanciado. por sua vez. Por public Robo() { inicializar(). Para isso.ALEATORIA.AGRESSIVA. de então. os algoritmos de movimentação ficam Ao relacionar essa estrutura com o código do jogo nota-se que a impossibilitados de serem reutilizados.movimenta. exemplo. pois só será necessário executar uma vez o processo complexo de criação desses objetos. Strategy.equals(acao)) { // Algoritmo para movimentação defensiva } else if (MovimentoEnum.equals(acao)) { // Algoritmo para movimentação agressiva } else if (MovimentoEnum. o padrão de projeto Adapter pode ser utilizado para mudança a ser observada é a implementação da interface Clo- adaptar a classe MovimentoAleatorio em uma estratégia que será neable. uma instância protótipo pode ser criada private void inicializar() { } com esses dados e sempre que for preciso uma cópia dela pode ser disponibilizada. Desta forma.equals(acao)) { // O algoritmo de movimentação aleatória é implementado // por terceiros através do método MovimentoAleatorio.dofactory. Aplicação do Prototype na classe Robo.execute(). Dito isso. pois com ele os algoritmos de movimentação serão Portanto. pois sempre que houver a necessidade muito alto para o sistema. ou seja. } } /** * Cria e retorna a cópia do objeto Robo */ @Override public Robo clone(){ return this. ALEATORIA implementa esse padrão é capaz de criar uma cópia de si mesmo. a classe Robo será refatorada para que fique com o abstraídos dentro de estratégias (classes) específicas.com Copyright . estão armazenados em uma base de dados. lação de objetos com alta complexidade de serem instanciados e que são utilizados diversas vezes. terceiros.execute() new MovimentoAleatorio(). uma defesa ou movimentos aleatórios! instância protótipo. os demais objetos serão criados através da cópia da * Pode ser um ataque. que possibilita a criação de um objeto idêntico ao uma classe adaptadora e como MovimentoAleatorio pertence a objeto original. Essa interface indica que Robo será capaz de criar uma definida pelo padrão Strategy. mover(MovimentoEnum. Com isso.DEFENSIVA). Já para o segundo caso (a ordenação de elementos em uma lis- ta). alteração a ser realizada é criar as estratégias de movimentação dos robôs. a interface que representa a abstração /** da coleção de algoritmos é a Strategy. /** * Implementação da estratégia de movimento agressivo.clone(). utilizando o operador new. e o método executar() é o res- ponsável pela implementação da estratégia de movimentação. separação esta que possibilita escolher */ public void executar(). Robo chuckNorris = robo.clone(). as opções para se deslocar de um lugar para da classe Jogo para que façamos uso dos benefícios adquiridos outro podem variar de acordo com a preferência do usuário.mover(MovimentoEnum. o código fica menos acoplado @Override devido à possibilidade de ele utilizar diferentes estratégias sem public void executar() { //Algoritmo para movimentação agressiva conhecer como elas são implementadas. Portanto. Os demais robôs serão criados a partir pode ser diferente. encapsular cada um deles e os tornar /** intercambiáveis. } O diagrama da Figura 2 ilustra a organização desse padrão. forme a estratégia escolhida. /** Aplicando o padrão Strategy * Interface que define a assinatura do método a ser O padrão Strategy trata diretamente de problemas relacionados * adotado para implementação das estratégias */ ao acoplamento do código. */ plar a classe que fará uso dos algoritmos apenas a uma abstração e public class MovimentoAgressivo implements MovimentoStrategy{ não a uma implementação. pode escolher fazer o caminho a pé. Todos os direitos reservados para DevMedia . conforme apresentado na Listagem 6. é estabelecida uma separação dos algo. carro ou ônibus. Já a classe Context é a classe que faz uso. a abordagem proposta na definição do Strategy é aco. Listagem 6.clone().setNome(“Chuck Norris”). Por exemplo. bigHero. rambo. Ela é responsável por definir * Implementação da estratégia de movimento defensivo.com tou a redução do processamento gasto para criar objetos complexos. Definição da interface e implementação das classes de estratégias. Assim. de forma transparente. Refatoração do jogo para utilização do método clone(). lembre-se que pode haver uma quantidade muito grande de Listagem 5. a primeira //Cria a instância protótipo Robo robo = new Robo(). ConcreteStrategyB e ConcreteStrategyC). Diagrama de classe Strategy – Fonte: http://www. exposto no diagrama da Figura 1. public class Jogo { Aplicando os conceitos desse padrão para solução do problema public static void main(String[] args) { arquitetural do método mover() (vide Listagem 2). como pode ser visto na Listagem 5.ALEATORIA).Refatorando código com padrões de projeto Após a refatoração da classe Robo é preciso atualizar o código No primeiro caso.mover(MovimentoEnum. con- Esta alteração consiste em criar somente um objeto robô utili.dofactory. ritmos de quem os usa. chuckNorris. a utilização desse pattern possibili- Figura 2. qual algoritmo utilizar de forma dinâmica. Ele resolve esses problemas ao definir public interface MovimentoStrategy { uma família de algoritmos. que com a adoção de Prototype.AGRESSIVA).setNome(“Big Hero 6”). } De acordo com essa figura. } } Como verificado no exemplo. a opção } de gravar informações em um banco de dados ou em disco rígido pode variar de acordo com a disponibilidade de espaço. bigHero. 18 Copyright . //Algoritmo para movimentação defensiva Dois ótimos exemplos da aplicação desse padrão de projeto } } são o Google Maps e a ordenação de elementos em uma lista.Proibido copiar ou distribuir. algoritmos de ordenação implementados e que eles podem ser escolhidos de acordo com cada situação. rambo. Assim. * Execução da movimentação definida pela estratégia. @Override public void executar() { das estratégias implementadas nas classes concretas. //Cria um novo robô através do clone da instância protótipo A interface MovimentoStrategy representa o artefato Strategy Robo rambo = robo. toda vez que for preciso criar um objeto. do método clone(). chuckNorris. Note que não será necessário definir uma nova instância. o caminho para chegar ao destino zando o operador new.setNome(“Rambo”). Robo bigHero = robo. a assinatura do método a ser implementado pelas classes concretas */ public class MovimentoDefensivo implements MovimentoStrategy{ (ConcreteStrategyA. //Cria um novo robô através do clone da instância protótipo Robo rambo = robo. facilitando a manutenção e desacoplando o código. pois a classe MovimentoAleatorio * não implementa a interface MovimentoStrategy */ Aplicando o padrão Adapter bigHero.mover(new MovimentoDefensivo()). responsável por encapsular e adaptar a Adaptee para A partir disso. visto que sua interface é nova ação de movimento. com essa refatoração o jogo ficou sem a possibilidade /** de uso do movimento aleatório. Porém. Diagrama do padrão Adapter – Fonte: http://www.setNome(“Chuck Norris”). exemplo. haviam vários modelos de tomadas e plugues antes se Robo é preciso alterar mais uma vez a classe Jogo. estruturas diferentes possam trabalhar em conjunto através da Essas estratégias. */ interface MovimentoStrategy. * O método mover() agora recebe a estratégia de movimentação. Observe que após a implementação do padrão Strategy foi rambo. Isso ocorreu porque essa classe não implementa a * ao invés de necessitar implementar o movimento. No Brasil. sem ter o conhecimento * de sua implementação. que define a interface do robô passará a ser executada conforme a estratégia enviada compatível para ser usada pela classe Client. Ou Um exemplo desse padrão no mundo real pode ser encontrado seja. possível isolar os algoritmos de movimento do robô em classes Robo chuckNorris = robo. /** * Executa o comando de movimentação. Conforme a Listagem 8. */ @Override public class Jogo { protected Robo clone(){ return this. Para conseguir que o jogo chuckNorris. public class Robo implements Cloneable { //Código suprimido. Outro como parâmetro.mover(new MovimentoAgressivo()).Já as classes MovimentoAgressivo e MovimentoDefensivo cor. chuckNorris. após a refatoração na clas. serão utilizadas para desacoplar o código do método mo. bigHero. tenha as mesmas possibilidades de movimentação.clone(). fornecido pela classe Movimen. por Assim como realizado anteriormente. toAleatorio.dofactory. já que ela está acoplada apenas a uma abstração.clone(). ciada. Todos os direitos reservados para DevMedia 19 .clone(). reusadas em outros locais. alterações. a lógica condicional será removida e a movimentação padrão.setNome(“Rambo”). também expostas na última listagem referen. Além disso. //Faz mais alguma coisa Figura 3. Adapter. a mudança foi feita para enviar ao método mover() a instância da estratégia de movimento do robô. Também conheci- Copyright . * Código parou de compilar. caso haja a necessidade de implementar uma que esta possa ser utilizada pelo Client. public static void main(String[] args) { } //Cria a instância protótipo } Robo robo = new Robo().mover(new MovimentoAleatorio()). esse design pattern permite que classes com respondem à implementação concreta desses algoritmos. Listagem 7. o padrão /** Adapter será adotado..com } /** Listagem 8. e também a classe como parâmetro para esse método (vide Listagem 7).Proibido copiar ou distribuir. será necessário apenas criar uma classe que implemente a nos adaptadores feitos para que os cartões de memória das má- interface MovimentoStrategy e passá-la para o método mover() quinas fotográficas digitais sejam utilizados nos laptops. Refatoração para adequar a chamada ao método mover com as * Cria e retorna a cópia do objeto Robo estratégias. exemplo interessante são as tomadas de energia. adequação da interface incompatível. e como se trata de uma classe de rambo.executar(). o padrão permite que as mesmas estratégias sejam Robo bigHero = robo. separadas. */ public void mover(MovimentoStrategy movimento) { //Faz alguma coisa movimento. É exatamente para atender a necessidade de adaptar coisas que } } o padrão estrutural Adapter deve ser aplicado. O diagrama apresentado na Figura 3 exibe a estrutura desse ver().setNome(“Big Hero 6”). terceiros não é possível refatorá-la. Assim.clone().. a classe Robo não precisará sofrer incompatível com a estrutura requerida pela classe cliente. do como Wrapper. Refatoração do método mover(). Nele está presente a interface Target. com AleatorioAdaptado.com/ que auxilia o profissional a produzir código de melhor qualidade. interface MovimentoStrategy corresponde à Target. /** * A classe de movimento aleatório agora está adaptada * à interface MovimentoStrategy. * no método de movimentação do robô. Todos os direitos reservados para DevMedia . como de- private MovimentoAleatorio comportamento. criamos a classe MovimentoAleatorioAdaptado.com – www. Ela deve implementar a interface chuckNorris. Assim o jogo poderá fazer uso do movimento fornecido por essa classe. de Campina Grande (UFCG). muitas residências não possuem tomadas de três pinos para receber os aparelhos com esse tipo de plugue public static void main(String[] args) { e para isso é necessário um adaptador.clone(). Classe para adaptar MovimentoAleatorio. definidas pelo padrão Strategy. saiba que eles @Override não foram especificados para serem aplicados em uma linguagem public void executar() { comportamento. apresentada na Listagem 9. de programação específica. Head First Design Patterns.tutorialspoint. produtos devem ter somente os plugues com a nova forma de três public class Jogo { pinos redondos.Refatorando código com padrões de projeto da padronização realizada pela ABNT. Design Patterns: Elements of Reusable Object-Oriented Software. Já um exemplo no desenvolvimento de software pode ser demonstrado no nosso jogo de robôs.setNome(“Rambo”). Para completar. é necessário implementar a classe que fará a adaptação de Mo. permitindo o seu uso Listagem 9. atorio? A aplicação do Adapter pode solucionar esse problema. e a classe MovimentoAleatorio corresponde à Adaptee. 1995. John Vlissides. */ /** bigHero. } Autor Por fim. Livro que exemplifica os padrões usando comparações com o mundo real. MovimentoStrategy e encapsular MovimentoAleatorio.mover(new MovimentoDefensivo()). monstrado no artigo. Pós-Graduando em Engenharia de Escrever código de qualidade depende de fatores como experi.clone(). especialista difundidos. a chuckNorris.Proibido copiar ou distribuir. E em sistemas computacionais. Classe com a refatoração para adaptar o movimento aleatório. Addison-Wesley. mais coeso e possibilitou a redução Links e Livros: no processamento para se criar objetos complexos. resolução de determinados problemas. para serem utilizados no âmbito computacional. Ralph Johnson. Uma prova disso é que no livro de } referência do GoF os exemplos são ilustrados em C++. ência da equipe de desenvolvimento e da aplicação de conceitos já desenvolve aplicando conceitos como TDD e revisão em pares. Coletânea de exemplos práticos com UML de padrões de projetos aplicados à Ainda que padrões de projeto sejam soluções abstratas para a linguagem Java.mover(new MovimentoAgressivo()). bigHero. a ser utilizada pelos desenvolvedores para debater a resolução de Livro de referência quando o assunto é padrões de projeto. Robo chuckNorris = robo. www. ficou muito mais simples criar novas possibilidades de Exemplos práticos de padrões de projetos com foco na plataforma Java. */ rambo. 2004. Pronto! Com isso. Correlacionando os artefatos desse padrão ao nosso exemplo. eles são uma referência http://www. Robo bigHero = robo.setNome(“Chuck Norris”). todas as estratégias de É Bacharel em Ciência da Computação pela Universidade Federal movimentação voltam a ser utilizadas.com/design_pattern/index. Porém. Ademais.mover(new MovimentoAleatorioAdaptado()).clone(). engenheiro de software.htm lamento dos algoritmos de movimentação em classes separadas. os Listagem 10. Kathy Lembre-se que os padrões de projeto não foram definidos apenas Sierra. padrão Strategy impossibilitou o uso da classe MovimentoAle. * Adaptador para encapsular a classe de movimento aleatório } * em uma estratégia } */ public class MovimentoAleatorioAdaptado implements MovimentoStrategy{ Eles podem ser aplicados em situações do cotidiano. disso. gabfeitosa@gmail. problemas na construção de sistemas computacionais. Como prova em Java e em aplicações que utilizam o conceito de Single-Page Application (SPA). * ao invés de necessitar implementar o movimento. http:// movimentação para o robô e de testá-las.oodesign. a classe Jogo (vide Listagem 10) precisa ser refatorada Gabriel Feitosa mais uma vez para que faça uso da nova classe Movimento. vimentoAleatorio para ser utilizada junto às outras estratégias /** * O método mover agora recebe a estratégia de movimentação. a refatoração que foi realizada no código do jogo resultou em um código menos acoplado. rambo.execute(). Isso ocorreu devido ao iso. Além disso. como é o caso dos padrões de projetos. Para isso.setNome(“Big Hero 6”). //Cria a instância protótipo Robo robo = new Robo(). Após a padronização.gabrielfeitosa. Eric Freeman. Software na Faculdade 7 de Setembro (FA7). 20 Copyright . Elisabeth Robson. Bert Bates. eles propiciam uma linguagem de comunicação comum Richard Helm. Lembra que a adoção do //Cria um novo robô através do clone da instância protótipo Robo rambo = robo. Erich Gamma. código mais organizado e manu. por isso. esse artigo páginas JSP. chegar em cada um dos estados o usuário dispara eventos. enten. a saber: o estado inicial (a exibição do formulário em si). descrever con- juntos de passos para os usuários no website de forma estruturada e reusável. parte do framework Spring MVC destinada à implementação e. Deste modo. Numa aplicação web cada estado de uma requisição representa um propósito específico e. Isso mentar uma modificação. com mais páginas ou Com o SWF o fluxo de navegação é construído por meio da defi- com mais opções de respostas para as ações disponíveis. no entanto. a manutenção de grandes sites pode ser complicada e páginas de resposta por meio da configuração de actions envolver bastante tempo estudando seus fluxos antes de imple- (ou handlers) de acordo com o estado da requisição. Estado das requisições em aplicações web para fazer esse trabalho.Proibido copiar ou distribuir.Aprenda a utilizar o Spring Web Flow Saiba como implementar fluxos de navegação em uma aplicação Web com um exemplo usando Spring e Hibernate F Fique por dentro rameworks Model-View-Controller são vastamen- te utilizados e seus benefícios são amplamente conhecidos. lançada em 2008. Todos os direitos reservados para DevMedia 21 . que a aplicação web se torna maior. após o clique no botão de submissão). ao o usuário pelas páginas do website com pouca escrita de código Java. tornando necessário escrever mais código nos handlers BOX 1. Por uma vez que os frameworks MVC mais conhecidos sua vez. sucesso (que resultará na exibição de uma página de sucesso). O SWF será utilizado tenção mais simples. do Spring Framework. encapsulam os detalhes a respeito do aten. nição dos estados pelos quais o usuário passa. a submissão de uma página de formulário fluxo de navegação é que. constantemente verificar o código para entender os fluxos. na medida em versão 2. se a estrutura da aplicação pode ter quatro ou mais estados possíveis. espe- por exemplo. A partir disso. Por exemplo. pode ser notado quando temos a exibição de uma página Com base nisso. de fluxos de navegação em aplicações web. necessário manter um mapa atualizado das páginas e Copyright . uma das principais vantagens da maioria Spring MVC. para gerenciar esses fluxos pode se tornar mais complicado. neste artigo vamos explorar uma solução de erro ou de sucesso dependendo da ação realizada dada pelo Spring para o gerenciamento do fluxo de navegação pelo usuário. ou seja. dimento das requisições de um usuário e renderizam Ademais. No Struts vemos isso ilustrado na para tornar possível a definição de sequências de passos que guiam medida em que escrevemos código Java em actions. a forma como o padrão Apresentaremos neste artigo o desenvolvimento de um projeto web MVC distribui responsabilidades nas camadas da que adota o padrão Model-View-Controller com o Spring Web Flow aplicação faz com que tenhamos camadas mais magras (SWF). Nesses casos. ou insucesso (que resultará na der o fluxo se torna mais difícil. invés de manter grandes parte da lógica do negócio em de forma reusável e de fácil manutenção. Iniciado como uma extensão Fluxos simples como o do exemplo citado são per. se os caminhos para chegar às aguardando (quando o formulário está sendo submetido. bem como ao Hibernate ORM na construção de uma dos frameworks MVC não é tão visível: a possibilidade aplicação web completa. cialmente aqueles que envolvem condições e múltiplos estados. é importante também por demonstrar como o SWF é integrado ao No entanto. em websites: o Spring Web Flow. Outro aspecto interessante sobre o gerenciamento do terá uma página ou handler correspondente. Por exemplo. consequentemente. Contudo. sua popularização ocorreu apenas com a maioria dos frameworks MVC. sua primeira versão estável foi lançada feitamente gerenciáveis pelos mecanismos nativos da em 2006. páginas são longos e/ou muito subdivididos. ou seja. seria exibição de uma página de erro). entre os eventos que fazem as passagens de um estado não gerenciam os estados das requisições (vide BOX 1). Neste cenário. o Struts e o Spring. de definir fluxos de navegação. é complexa. 0.2 (e/ou um plugin respectivo do Maven para Eclipse) ou gerenciar as dependências do projeto manualmente. Portanto. Para isso. o leitor deve ficar à vontade para mostra a Figura 3.4 (Luna. Detalhes do projeto exemplo O projeto será construído com a IDE Eclipse. Dessa forma. selecione Web > Dynamic Web Project. A arquitetura da aplicação inclui ainda uma Figura 1.3. como assim como o driver JDBC solicitado para a conexão com o banco 22 Copyright . vamos inserir as dependências do nosso projeto.4. Criando o projeto e configurando as dependências Primeiramente. na janela New Project. para desenvolvimento Java EE) por já possuir integração nativa com o gerenciador de dependências Maven. conforme a Figura 1. após acessar as opções de menu File > New Project > Other. clique com o botão direito sobre necessárias para utilizar o Spring MVC e o Hibernate ORM.Aprenda a utilizar o Spring Web Flow para outro temos as transições de estado. assim como algu- mas noções sobre padrões arquiteturais bastante utilizados em soluções dessa natureza. no entanto. Vamos configurá-lo para rodar no container Tomcat 8. onde utilizar versões diferentes do Tomcat ou outro container web Java. crito na Listagem 1. Será criado. Janela de seleção de tipo de projeto no Eclipse camada de serviço rudimentar. clique em Finish. Além disso.2. conforme des- como Jetty ou JBoss. Clicando em Next será exibida a janela com as propriedades Figura 2. Todos os direitos reservados para DevMedia . Repare que incluímos nesse arquivo todas as dependências pendências Maven. Todo esse mecanismo é especificado em regras dentro de um arquivo XML. nosso exemplo ficará bastante completo e fornecerá ao leitor todos os passos necessários para iniciar o desenvolvimento com os frameworks citados. o qual chamaremos de GestaoAcademicaWeb. criemos um Dynamic Web Project no Eclipse. Com o projeto criado. mais do que demonstrar o uso do SWF. Sendo assim. o leitor deve explorar a documentação correspondente ou artigos anteriores publicados nessa revista sobre o uso desses recursos. persistirá dados em um banco de dados MySQL. apresen- taremos um exemplo completo da integração entre Spring Web Flow. o que viabiliza o reuso e diminui a escrita de código. assim.Proibido copiar ou distribuir. é importante destacar que não é objetivo desse artigo discorrer sobre as arquiteturas e padrões de projeto.2. sugerimos o uso do Eclipse em versão superior à 4. com o suporte do Spring MVC 4. No exemplo que apresentaremos nesse artigo focaremos nas principais vantagens do SWF ilustrando as maiores contribui- ções dadas por esse projeto ao desenvolvimento web.11 para implementá-la. A camada de persistência seguirá o padrão DAO e utilizaremos o framework Hibernate ORM 4. rodará no Tomcat 8 e sua implemen- tação seguirá o padrão Model-View-Controller. Caso essa não seja a sua versão do Eclipse. Dessa forma. o projeto e selecione Configure > Convert to Maven Project.xml. Spring MVC e Hibernate. No entanto. vamos integrá-lo ao gerenciador de de. responsável por fazer a ligação entre a camada de controle e a camada de dados usando uma simplificação do padrão Service Layer. Feito isso. além de demonstrar seu uso de forma integrada com o Spring MVC e Hibernate. o arquivo pom. Já a nossa versão do SWF será a 2. Janela de propriedades do projeto do projeto (vide Figura 2). bem como sobre os frameworks Spring e Hibernate. é necessário instalar o Maven em versão igual ou superior à 3. futuramente.Proibido copiar ou distribuir. o datasource. devemos criar também os arquivos \src\ configurações que o Hibernate usa para acessar o banco de dados hibernate.7</target> <artifactId>hibernate-core</artifactId> </configuration> <version>4.springframework</groupId> <groupId>GestaoAcademicaWeb</groupId> <artifactId>spring-tx</artifactId> <artifactId>GestaoAcademicaWeb</artifactId> <version>4. As propriedades contidas nesse Em hibernate.0. Em seguida.1</version> </dependency> <configuration> <dependency> <source>1.apache.de dados.11. Mapeamento Objeto-Relacional é a técnica utilizada para tornar possível a representação das mada de visão serão armazenadas e. como URI.RELEASE</version> <version>0.Final</version> </plugin> <scope>compile</scope> <plugin> </dependency> <artifactId>maven-war-plugin</artifactId> <dependency> <version>2. como o diretório em que as páginas da ca. Mapeamento Objeto-Relacional ao longo do artigo.2. Todos os direitos reservados para DevMedia 23 . ário e senha (vide Listagem 2).0.2.0. configurações classes da aplicação – projetadas a partir do paradigma da Orientação a Objetos – em entidades de do SWF.springframework.webflow</groupId> <plugin> <artifactId>spring-webflow</artifactId> <artifactId>maven-compiler-plugin</artifactId> <version>2.2.6</version> </dependency> </dependency> <dependency> </dependencies> <groupId>org.2.2.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://maven.org/POM/4. Listagem 1.4</version> <dependencies> </dependency> <dependency> <dependency> <groupId>org. arquivo são.xml.RELEASE</version> w3.xml. tes ao mapeamento objeto-relacional (Vide BOX 2).springframework</groupId> <groupId>mysql</groupId> <artifactId>spring-context</artifactId> <artifactId>mysql-connector-java</artifactId> <version>4.7</source> <groupId>org.0” xmlns:xsi=”http://www.1. que encapsulam as confi.0 http://maven.RELEASE</version> <version>3. Também aproveitamos esse arquivo para armazenar as um banco de dados relacional – projetadas a partir do paradigma Relacional e da Normalização.0.RELEASE</version> </resource> </dependency> </resources> <dependency> <plugins> <groupId>org.xml inclui as con- figurações do Spring. gurações do Hibernate e do Spring MVC e cujos códigos-fontes Agora.0.3.xml. vamos definir o arquivo \WEB-INF\jdbc.4. como veremos BOX 2. então. Código-fonte do arquivo pom.0</modelVersion> <groupId>org.0.springframework</groupId> </project> <artifactId>spring-web</artifactId> Copyright .1-SNAPSHOT</version> </dependency> <packaging>war</packaging> <dependency> <build> <groupId>org. como.2.xml serão feitas as configurações corresponden. Já o arquivo spring-context.0.2.cfg.4</version> <groupId>jstl</groupId> <configuration> <artifactId>jstl</artifactId> <warSourceDirectory>WebContent</warSourceDirectory> <version>1.org/xsd/maven-4.hibernate</groupId> <target>1. <version>4. usu- página desta edição. chamadas em spring-context.springframework</groupId> <exclude>**/*.apache.xml e spring-context.properties para podem ser vistos junto ao código disponível para download na armazenar as configurações de acesso ao banco.springframework</groupId> <sourceDirectory>src</sourceDirectory> <artifactId>spring-webmvc</artifactId> <resources> <version>4.RELEASE</version> <version>5.java</exclude> <artifactId>spring-orm</artifactId> </excludes> <version>4.RELEASE</version> <resource> </dependency> <directory>src</directory> <dependency> <excludes> <groupId>org. por exemplo.2.org/ </dependency> POM/4.xsd”> <dependency> <modelVersion>4.cfg.2</version> <failOnMissingWebXml>false</failOnMissingWebXml> </dependency> </configuration> <dependency> </plugin> <groupId>commons-dbcp</groupId> </plugins> <artifactId>commons-dbcp</artifactId> </build> <version>1.2.2.apache. <project xmlns=”http://maven. dialect=org. projeto deve ficar como mostrado na Figura 5. como clicar em um link ou como onde armazenaremos os fluxos. Estrutura do projeto padrões que serão adotados. Mais além. 24 Copyright . universidade cujo fluxo é bastante simples. Código do arquivo jdbc. e selecione New > jdbc.driverClassName= com. cada estado terá uma página corres.hibernate. a estrutura do resposta a uma submissão de formulário. no nosso caso.mysql. chega espontaneamente. Todos os direitos reservados para DevMedia . embora não seja necessário seguir a ordem de criação dos arquivos sugerida nesse artigo. View-state 1. lembremos que. os handlers responsáveis pelas submissões de for- O fluxo da aplicação exemplo mulários são representados como um “sub-estado” chamado Para começar. A partir disso.Aprenda a utilizar o Spring Web Flow Figura 4. como segue: que esses eventos podem levar a dois tipos básicos de estado: 1.MySQLDialect a Figura 4. com SWF. Criando o pacote-base da aplicação Figura 3. criaremos. O próximo passo é criar a estrutura do projeto de acordo com os Figura 5. por exemplo. também. ocorrem após o usuário disparar eventos.dialect. clique com o botão direito sobre a pasta Listagem 2. o diretório WEB-INF/flows.com. Java Resources\src.properties. Sendo assim. que existe entre view-state e um end-state. um fluxo é composto action-state.devmedia. como resultado de um evento.username=gestaoacademica jdbc. especificamos apenas na. Convertendo o projeto para Maven Neste ponto vale ressaltar que. Por fim. por um conjunto de estados.jdbc. os passos que demonstramos simplificam o desenvolvimento. já que vemos que os arquivos fazem referências uns aos outros em alguns casos. Dessa forma. jdbc. consequentemente. saiba três estados (dois view-states e um end-state). • View-state: representado por uma página na qual o usuário cação – e service – onde ficarão as classes da camada de serviço. além do padrão DAO para a camada de persistência. uma arquitetura MVC. além do dao – onde serão armazenadas as classes da camada de persistência da nossa apli. digite “br. Como nesse artigo criaremos um cadastro de docentes de uma pondente e as mudanças de estado e. no Package Explorer do Eclipse.gestaoacademicaweb” no jdbc.databaseurl=jdbc:mysql://localhost:3306/gestaoacademica campo Name e clique em Finish.Proibido copiar ou distribuir. Nossas páginas (a camada view) ficarão no diretório WEB-INF/ • End-state: representado por uma página na qual o usuário chega views. uma camada de serviço. de pági. Conforme demonstra jdbc. representado pela página de listagem.password=gestaoacademica Dentro do pacote-base vamos repetir o mesmo procedimento para criar os pacotes control e model. digitando um endereço.Driver Package para criar o pacote-base do projeto. como mostra o código-fonte visto nas Listagens 5 e 6. chamadas às respectivas Copyright . o usuário será As camadas de serviço e controle direcionado para o formulário de cadastro. No nosso exemplo implementaremos a camada de serviço com uma simplificação do padrão Service Layer (BOX 4). o usuário é mantido na página com a listagem de uma pequena camada de serviço para fazer com que a aplicação docentes após a operação. “excluir”. para habilitar o Hibernate a persistir os objetos no banco de dados. vemos em Figura 6. a classe Docente. Na sequência. Nele. ambos por meio de cliques em links. começan. dentro do pacote model. Isso ocorre na optar por inserir o docente ou cancelar a operação. construiremos o fluxo com o 3. cada atributo da classe é associado a um campo em sua respectiva tabela. O código-fonte desse artefato pode ser visto na Listagem 3. ilus. nos métodos adicionarDo- partiremos para a implementação da aplicação exemplo. Como a classe DocenteDAOImpl implementa a interface DocenteDAO. removerDocente() e listar(). direcionado para uma página de resposta. após a operação de cadastro ser realizada com sucesso o as chamadas à camada de persistência. para realizar as operações de inserção (por meio do método save()). crie Implementação do projeto exemplo dois arquivos no pacote br. é de negócio encapsulada nos controllers. configurações ou para fazer verificações lógicas. “cancelar” e “inserir”. interpretadas pelo compilador para realizar uma determinada tarefa. podemos imple- mentar a camada de persistência. Todos os direitos reservados para DevMedia 25 . a classe rios à construção do nosso projeto com o SWF. BOX 3. vamos configurar o mapeamento objeto-relacional de Docente no arquivo hibernate. de serviço e controle. Finalizando. respectivamente). o que pode ser feito com o código da Listagem 4. então. DocenteServiceImpl.xml.cfg . service: a interface DocenteService e sua implementação. Vemos. Com o JavaBean da camada de modelo criado. Anotações Anotações são recursos para a declaração de metadados – dados que descrevem outros dados – úteis para localizar dependências. Em seguida. Se escolher incluir um docente. digite o nome Docente e clique em Finish. representado pelo formulário de cadastro de do pelas camadas de modelo e persistência e depois pelas camadas docentes. fique “magra” e possibilite que as regras de negócio sejam en- Uma vez na página do formulário de docentes o usuário pode capsuladas em camadas mais simples e reusáveis. A partir de agora. por meio da anotação @Column. Isso significa que da página ini. exclusão (com o método delete()). Representação do fluxo de nosso projeto-exemplo seu corpo a implementação dos métodos que realizam as operações com o banco de dados. bem como para recuperá-los em uma operação de listagem (listarDocentes()). Sen- do assim. representado pela página de resposta ao cancelamento. então. As camadas de modelo e persistência trando seus estados e transições. A interface DocenteDAO declara os métodos para inserir e excluir registros do tipo Docente no banco de dados (adicionarDocente() e removerDocente(). com o botão direito sobre o pacote. para incluir novo docente ou excluir docentes. Nas seções anteriores descrevemos todos os conceitos necessá. Para isso. Vamos iniciar a nossa implementação criando. Essas definições serão. objeto principal desse artigo.2. View-state 2. SWF.gestaoacademicaweb. selecione a opção New > Class. End-state. que consiste em uma interface (DocenteDAO) e sua implementação (DocenteDAOImpl). Se optar por medida em que os serviços assumem a responsabilidade de fazer inserir. Nesses métodos o Hibernate é chamado Podemos ver que entre os estados temos as transições “novo”. E se escolher excluir Após implementarmos o modelo e a persistência vamos codificar um docente. Se escolher cancelar.Proibido copiar ou distribuir. Como podemos observar também. A Figura 6 demonstra o fluxo do nosso projeto exemplo. único JavaBean do nosso projeto. deixando assim a lógica usuário é direcionado de volta à listagem. e listagem (através do método cial – a listagem de docentes – temos eventos que levam o usuário list()). podemos observar anotações (vide BOX 3) do Hibernate que asso- ciam esta classe/entidade à sua respectiva tabela no banco de dados (através da anotação @Table). cente().com.devmedia. gestaoacademicaweb.com. public void adicionarDocente(Docente docente).util. Código-fonte do arquivo hibernate. @Autowired } private SessionFactory sessionFactory. incluindo o mapeamento } objeto-relacional da classe Docente.getCurrentSession().gestaoacademicaweb.dao. } package br.save(docente).gestaoacademicaweb.SessionFactory. } import org.Id.Autowired. @Column(name=”MATRICULA”) private String matricula.stereotype.devmedia.matricula = matricula. return id. return nome. public String getTitulacao() { return titulacao.getCurrentSession() <!DOCTYPE hibernate-configuration PUBLIC .model.model. import org. aplicação passam a compartilhar funcionalidades comuns encapsuladas nos serviços. } <hibernate-configuration> } <session-factory> </session-factory> public List<Docente> listarDocentes() { return sessionFactory. import javax. @Column(name=”TITULACAO”) private String titulacao.sourceforge. como demonstram as Listagens 7 e 8.List.Aprenda a utilizar o Spring Web Flow Listagem 3.springframework. Por sua vez.com.Proibido copiar ou distribuir.Docente” /> </session-factory> } </hibernate-configuration> } 26 Copyright .delete(docente).hibernate. anotação do Spring utilizada para descrevê-la como import javax.persistence.Docente. Código-fonte da interface DocenteDAO.net/hibernate-configuration-3.devmedia.Entity. cujo código public class Docente { pode ser visto na Listagem 9. respondente às requisições de acordo com as regras de negócio definidas. uma vez que os módulos da private String nome. Dessa forma.persistence.model.dao. public void removerDocente(int id) { <?xml version=’1.persistence.0. } import br.annotation. id). } public void adicionarDocente(Docente docente) { sessionFactory. } public void removerDocente(int id). this. na camada de controle. e vemos também que a classe é declarada com package br. </hibernate-configuration> } <mapping class=”br.springframework.nome = nome.id = id. os dados a serem persistidos devem ser recebidos import javax. “-//Hibernate/Hibernate Configuration DTD//EN” if (null != docente) { “http://hibernate. Todos os direitos reservados para DevMedia .list(). import javax.titulacao = titulacao.util.devmedia.devmedia.Docente. Código-fonte da classe Docente.Column. Padrão Service Layer @Column(name=”ID”) @GeneratedValue Service Layer é um padrão de projeto orientado a objetos que visa organizar a lógica de negócio private Integer id.com. em serviços que.gestaoacademicaweb. o @Column(name=”NOME”) esforço conceitual de manutenção e gerenciamento destas é reduzido.com.devmedia.gestaoacademicaweb.xml.getCurrentSession(). package br.model. @Id BOX 4. compartilham funcionalidades.dtd”> sessionFactory.com. Listagem 4 . public void setMatricula(String matricula) { import org. import br.List.GeneratedValue.beans.class. parte da camada de serviço da aplicação. operações na camada de persistência.factory. começando pela classe DocenteController.devmedia. public String getNome() { public List<Docente> listarDocentes().getCurrentSession(). Código-fonte da classe DocenteDAOImpl.Table.load(Docente.com.Repository.createQuery(“from Docente”).gestaoacademicaweb.0’ encoding=’utf-8’?> Docente docente = (Docente) sessionFactory. responsável por dar o tratamento cor- import javax. @Repository } public class DocenteDAOImpl implements DocenteDAO { public void setTitulacao(String titulacao) { this.cfg. devidamente categorizados. this.persistence. @Service. } } public void setNome(String nome) { Listagem 6. Vamos então criar a camada de controle no pacote @Entity @Table(name=”DOCENTES”) control. } public void setId(Integer id) { public interface DocenteDAO { this.persistence. public String getMatricula() { return matricula. Listagem 5. public Integer getId() { import java. import java. *.devmedia.Autowired.Listagem 7.control. agora.Transactional. } Dito isso.DocenteController” />.service. O código-fonte do formulário de cadastro de docenteService. } docentes pode ser visto na Listagem 11.jsp). x ml” public void removerDocente(int id) { docenteDAO.com. com o botão direito sobre o diretório WEB-INF/views. aos estados declarados no fluxo. Código-fonte da classe DocenteController.gestaoacademicaweb. tual reuso dos fluxos criados – recomendamos a criação de um arquivo XML para cada fluxo da aplicação.gestaoacademicaweb.devmedia. Código-fonte da implementação do serviço DocenteServiceImpl.gestaoacademicaweb.devmedia. package br.factory.gestaoacademicaweb. } ção utilizando a tag <bean>. a camada de visão.util.stereotype.springframework.annotation.Docente. foram incluídas em spring-context. declaramos os controllers da nossa aplica- return docenteDAO.annotation. } Para manter o código estruturado – além de permitir um even- Listagem 8.com.Controller.adicionarDocente(docente).Autowired.com. @Transactional com extensão XML. que será identificado pelo nome docenteController. Web Flow. serviço e persistência con- public interface DocenteService { cluídas.control. localizado em /WEB-INF/flows/.DocenteDAO. e a página de public List<Docente> listarDocentes() { List<Docente> docentes = docenteService.Proibido copiar ou distribuir. private DocenteDAO docenteDAO.listarDocentes().annotation.gestaoacademicaweb. Vamos.jsp” e public void removerDocente(int id) { clique em Finish. zenaremos estes arquivos XML dentro de WEB-INF/flows. import br. No nosso caso chamamos o public void adicionarDocente(Docente docente) { fluxo de inserirDocente.springframework.service. import br. import br.jsp).removerDocente(id). e selecionando New > File.transaction. @Autowired As principais modificações que fizemos em spring-context. como verificado no trecho <bean name=”docenteController” class=”br.removerDocente(id).com. Dito isso.springframework. import org.adicionarDocente(docente).com. mostra a instrução docenteService. especialmente das classes FlowHandlerMapping import org.devmedia. de Docentes (inserir_docente_form. enquanto é possível } visualizar sua aparência na Figura 7.devmedia.gestaoacademicaweb. e FlowHandlerAdapter. xml para configurar o SWF se referem ao mapeamento dos @Transactional fluxos que nosso website possui.devmedia.Service.com. o que é feito clicando com o botão direito sobre este diretório import org.listarDocentes().model.DocenteService.beans.Docente. import java.util. onde há a declaração <webflow:flow- @Transactional location path=”/W EB -I N F / f lows / inse r irDoc e nte. configurações correspondentes ao SWF no arquivo spring-context. Código-fonte da interface DocenteService.gestaoacademicaweb.springframework. xml. no diretório WEB-INF/views. ainda não alteraremos o XML recém-criado. como package br. . Observe nessa listagem que os métodos acessam a camada de serviço para realizar as operações com o banco de dados. dentro do diretório flows crie o arquivo inserirDocente import br.List. Uma vez que é necessário realizar as import org. controle.com. resposta ao cancelamento (cancelado.devmedia. id=”inserirDocente” />. Implementando o fluxo com o Spring Web Flow Com as camadas de modelo. @Service modificar as configurações do Spring alterando seu arquivo de con- public class DocenteServiceImpl implements DocenteService { figuração para que fique conforme demonstrado na Listagem 10. já é possível implementar o fluxo da aplicação. que especifica que o fluxo identificado } por inserirDocente está declarado no arquivo de mesmo nome.com. Copyright .service.stereotype. Podemos verificar sua descrição no nó docenteDAO. public void removerDocente(int id). Todos os direitos reservados para DevMedia 27 .adicionarDocente(docente). vamos criar as @Autowired páginas da nossa camada de visão: um formulário para cadastro private DocenteService docenteService.springframework. import java.gestaoaca- } demicaweb.xml. } <webflow:flow-registry>.gestaoacademicaweb.util.factory. que conterá as páginas que corresponderão public List<Docente> listarDocentes().com. uma página que exibirá uma lista dos docentes cadastrados (listar_docente. bem como public void adicionarDocente(Docente docente). No nosso caso arma- package br.beans. padrão do SWF. No mais. os chamados flow handlers do Spring import org. Na janela de propriedades do arquivo. @Controller Desenvolvendo as páginas da camada de visão public class DocenteController { Antes de iniciar o desenvolvimento do fluxo.devmedia. Todas serão armazenadas return docentes. import br. public List<Docente> listarDocentes() { Seguindo em frente.List.Docente.dao. public void adicionarDocente(Docente docente) { selecione New > JSP File. Vale lembrar que no Listagem 9. nosso exemplo temos apenas um controller.devmedia. } digite no campo File Name o nome “inserir_docente_form.xml as configurações import java. docenteService.jsp). show_sql”>true</prop> </html> </props> </property> </bean> <tx:annotation-driven /> <bean id=”transactionManager” class=”org.orm. Formulário de cadastro de docentes <bean class=”org. rações do SWF. do pacote form.xml” id=”inserirDocente” /> </webflow:flow-registry> Figura 7.Aprenda a utilizar o Spring Web Flow Listagem 10.springframework.springframework.control.username}” <td><form:input path=”titulacao” /></td> p:password=”${jdbc.gestaoacademicaweb” /> <title>Cadastro de Docentes</title> </head> <body> <bean id=”jspViewResolver” class=”org. Já a associação entre os formulários </bean> e as respectivas classes na camada de modelo é feita por meio da <bean name=”docenteController” class=”br.view. <%@taglib uri=”http://www.factory.HibernateTransactionManager”> <property name=”sessionFactory” ref=”sessionFactory” /> </bean> <webflow:flow-executor id=”flowExecutor”/> <webflow:flow-registry id=”flowRegistry”> <webflow:flow-location path=”/WEB-INF/flows/inserirDocente.JstlView” /> <form:form method=”post” modelAttribute=”docenteModel”> <property name=”prefix” value=”/WEB-INF/views/” /> <property name=”suffix” value=”.hibernate4. <html> <context:annotation-config /> <head> <context:component-scan base-package=”br.servlet. como é mostrado nos trechos de código iniciados por <form:input>.dialect”>${jdbc.servlet.commons.driverClassName}” <td>Titulação:</td> p:url=”${jdbc.password}” /> </tr> <tr> <bean id=”sessionFactory” <td> class=”org.properties” /> <tr> <td>Matrícula:</td> <bean id=”dataSource” <td><form:input path=”matricula” /></td> </tr> class=”org.FlowHandlerMapping”> <property name=”flowRegistry” ref=”flowRegistry”/> Para construir esse formulário fizemos uso dos pacotes de taglibs <property name=”order” value=”0”/> </bean> do Spring.dbcp.BasicDataSource” destroy-method=”close” <tr> p:driverClassName=”${jdbc.org/tags/form” prefix=”form”%> .hibernate4.springframework. como vemos em .InternalResourceViewResolver”> <h3>Formulário de Cadastro de Docentes</h3> <property name=”viewClass” value=”org.orm..config.org/tags” prefix=”spring”%> <?xml version=”1.cfg.jsp” /> <table> </bean> <tr> <td>Nome:</td> <bean id=”propertyConfigurer” <td><form:input path=”nome” /></td> class=”org. Listagem 11.devmedia.com.springframework.webflow. Código-fonte do formulário de cadastro de docentes. incluindo as configu. </beans> Nesse trecho constatamos que o formulário de cadastro de do- 28 Copyright .xml.mvc.FlowHandlerAdapter”> zada para criar os campos do formulário conforme verificado em <property name=”flowExecutor” ref=”flowExecutor”/> <form:input path=”nome” />.LocalSessionFactoryBean”> <input type=”submit” name=”_eventId_inserir” value=”Salvar”/> <property name=”dataSource” ref=”dataSource” /> </td> <property name=”configLocation”> <td> <value>classpath:hibernate.web.servlet.PropertyPlaceholderConfigurer” </tr> p:location=”/WEB-INF/jdbc. Todos os direitos reservados para DevMedia .view.mvc.servlet.dialect}</prop> </body> <prop key=”hibernate.springframework.gestaoacademicaweb propriedade modelAttribute na tag <form>.beans.0” encoding=”UTF-8”?> <%@taglib uri=”http://www.xml</value> <input type=”submit” name=”_eventId_cancelar” value=”Cancelar”/> </property> </td> </tr> <property name=”hibernateProperties”> </table> </form:form> <props> <prop key=”hibernate.devmedia.springframework.web.webflow.com.databaseurl}” p:username=”${jdbc.apache.springframework.springframework.Proibido copiar ou distribuir.. em especial.DocenteController” /> <form:form method=”post” modelAttribute=”docenteModel”>.springframework. Código-fonte do arquivo spring-context. Essa taglib é utili- <bean class=”org. Listagem de Docentes Agora que as páginas foram criadas podemos fazer a implemen- No código dessa página os eventos disponíveis são cliques tação do fluxo da aplicação modificando o arquivo inserirDocente. O código <h3>Docentes Cadastrados</h3> da página de resposta de cancelamento é bastante simples e é <h3><a href=”${flowExecutionUrl}&_eventId=novo”>+ Novo Docente</a></h3> apresentado na Listagem 12. respectivamente. Já o código-fonte da listagem de <c:if test=”${!empty docenteList}”> docentes é demonstrado Listagem 13. pageEncoding=”UTF-8”%> mos mais adiante. cente”/>.dtd”> <html> declarações dos campos para indicar a que atributo da classe cada <head> campo de formulário será associado.titulacao}</td> <td><a href=”${flowExecutionUrl}&_eventId= excluir&docenteId=${docente. dispará-lo. de cadastro de docentes) e um end-state (operação cancelada). como demonstrado na Listagem 14. <meta http-equiv=”Content-Type” content=”text/html.jsp e listar_docentes. <body> tos pelo usuário. a propriedade path é usada nas “http://www. e isso é implementado na declaração dos links.Do- = ${docente. flowExecutionUrl. e a vere. </head> jsp.xml.model. por meio do parâmetro cadastro de docentes.w3. Visto que nosso pro- no banco – devidamente recuperados pelas demais camadas da jeto possui dois view-states (listagem de docentes e formulário aplicação. por exemplo.cente é associado à classe da camada de modelo identificada por Listagem 12.devmedia. quando este clica em um botão.matricula}</td> <td>${docente.sun.gestaoacademicaweb. Código-fonte da página de cancelamento.01 Transitional//EN” inserirDocente. enquanto sua aparência <table border=”1”> pode ser vista na Figura 8. que representam.com. Com isso. charset=UTF-8” Essa identificação é configurada no arquivo do fluxo. Aqui é importante xml. <tr> <th>Nome</th> <th>Matrícula</th> <th>Titulação</th> <th>&nbsp. como em docenteModel. <title>Listagem de Docentes</title> Agora vamos criar os arquivos cancelado. feita no trecho <var name=”docenteModel” <a href=”${flowExecutionUrl}&_eventId=excluir&docenteId class=”br. O primeiro elemento lembrar que os eventos devem ser identificados pelo prefixo que devemos notar nesse arquivo é a declaração da variável _eventId. ou num <h3>Processo de cadastramento cancelado</h3> </body> link.id}”>.com/jsp/jstl/core” prefix=”c”%> de docentes é identificado por _eventId_inserir. a página de resposta de <body> cancelamento e a listagem dos docentes cadastrados. Por exemplo. Todos os direitos reservados para DevMedia 29 .id}”>Excluir</a></td> </tr> </c:forEach> </table> </c:if> </body> </html> Figura 8. nos links para “novo docente” e “excluir”.Proibido copiar ou distribuir. os estados do fluxo são percorrer uma coleção e exibir os registros de docente cadastrados descritos em nós XML com o sufixo -state. Nesse caso.org/TR/html4/loose. o botão Salvar no formulário de cadastro <%@taglib uri=”http://java. inserirDocente). O restante da página utiliza taglibs JSTL para Como demonstrado nessa listagem. Código-fonte da listagem de docentes. quando apresentarmos o conteúdo do arquivo <!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4. como pode ser vis- to no trecho <input type=”submit” name=”_eventId_inserir” <html> <head> value=”Salvar”/>. ou seja. docenteModel.</th> </tr> <c:forEach items=”${docenteList}” var=”docente”> <tr> <td>${docente. charset=UTF-8”> A passagem de uma página para outra – que o SWF identifica <title>Insert title here</title> </head> como transição entre estados – é feita por meio do disparo de even.nome} </td> <td>${docente. Copyright . <%@ page language=”java” contentType=”text/html. cada evento disponível nas páginas </html> deve ser identificado (na sua propriedade name) pelo prefixo _even- tId na declaração do elemento de página que foi construído para Listagem 13. Essa variável é utilizada para descrever a associação Note também que incluímos no link o fluxo a que esse evento entre a classe Docente na camada de modelo e o formulário de se refere (no nosso caso. algo bastante celebrado na de docentes no banco.Aprenda a utilizar o Spring Web Flow utilizamos os nós <view-state> e <end-state> para declarar Para isso.docenteList”/> chamar de pais da Unified Modeling Language (UML). NOME VARCHAR(100). luate expression=”docenteController. Por exemplo. Nesse trecho. no caso. no navegador. as páginas que ele pode visitar e os eventos que </transition> </view-state> dispara pelo caminho. está mais simples do que o constru- sição como <transition on=”inserir” to=”inserirDocenteAction” ído usando outros frameworks MVC. permitindo que os fluxos sejam reutilizados não só em outras partes do próprio site. uma vez dispa. Esse recurso é utilizado novamente na listagem de docen- de docentes com o nó <action-state>. conforme a marcação <evaluate expression=”docenteController id=”inserirDocenteAction”>. especialmente das Para o evento de submissão do formulário.org/2001/XMLSchema-instance” ramos nesse artigo. <evaluate expression=”docenteController. Todos os direitos reservados para DevMedia .adicionarDocente(docenteModel)” /> TITULACAO VARCHAR(100) <transition to=”listar” /> ).jsp” model=”docenteModel”> Listagem 15. xsi:schemaLocation=”http://www. <view-state id=”form” view=”/WEB-INF/views/inserir_docente_form. Esse conceito tornou possível o encapsulamento do fluxo. note que também é indicado o escopo Listagem 14. Para tanto. como o Struts. camadas de controle e visão.w3.jsp”/> nuindo a escrita de código.gestaoacademicaweb. Grady Booch e James Rumbaugh. Com isso nosso exemplo está <var name=”docenteModel” class=”br. enquanto a propriedade to. será realizada durante o action-state inserirDocenteAction.listarDocentes()” result=”viewScope. <transition on=”inserir” to=”inserirDocenteAction” /> <transition on=”cancelar” to=”cancelado” /> CREATE TABLE DOCENTES ( </view-state> ID INT PRIMARY KEY AUTO_INCREMENT.docenteId” atividades ou espera por eventos.docenteId” value=”requestParameters. na marcação Nesse segundo exemplo vemos outro recurso do SWF ser <transition on=”cancelar” to=”cancelado” />. A propriedade on de uma transição indica em que que o método listarDocentes() seja executado na renderização da evento ela deve ser disparada. que significa que a variável estará <?xml version=”1. e definimos as transições em nós . </action-state> <view-state id=”listar” view=”/WEB-INF/views/listar_docentes. da classe DocenteCon. 30 Copyright . Nesse trecho fazemos com que o action-state inserirDocenteAction Spring.xml. sua integração Salvar). especificamos o handler do formulário de cadastro Model)”/>. seja acionado quando o evento inserir for disparado (podemos ver Também é importante ressaltar que o SWF é perfeitamente in- na Listagem 11 que esse evento está associado ao clique no botão tegrável a outros frameworks MVC.com. no trecho <action-state tes.springframework. declaramos uma tran. Código-fonte do fluxo inserirDocente. como mostra o trecho <eva- esses estados. No entanto. para listagem de docentes. qual estado o usuário é direcionado. a última coisa que falta para nosso projeto ser concluído http://www. mais <evaluate expression=”docenteController. especificamos o nó <evaluate>. dimi- <end-state id=”cancelado” view=”/WEB-INF/views/cancelado. na medida em que menos código precisou ser escrito. a view-state listar).springframework. com o Spring MVC é mais interessante.Proibido copiar ou distribuir.org/schema/webflow/ spring-webflow-2. fazer parte do mesmo projeto. executa algumas <transition on=”excluir” to=”listar”> <set name=”requestScope.adicionarDocente(docente- Por sua vez.devmedia. eventualmente. comunidade de desenvolvedores. o que pode ser feito após iniciar o Tomcat e Docente”/> digitar. da variável (viewScope.model.org/schema/webflow” xmlns:xsi=”http://www. mas não os explo- <flow xmlns=”http://www. ou o próprio />. Nesse artigo.org/schema/webflow Com isso. Vale destacar que o código. vemos como esse type=”long” /> conceito é adotado para descrever a navegação do usuário. mas em outras aplicações.listarDocentes()” result=”viewScope. vamos usar o script de criação da tabela descrito na Listagem 15. utilizado: o retorno do método é armazenado em uma variá- rado o evento cancelar o usuário será encaminhado para o estado vel que pode ser acessada na camada de visão.jsp”> <on-render> Ivar Jacobson.0” encoding=”UTF-8”?> disponível apenas no estado em que ela foi declarada. Outros escopos existem. A propriedade cancelado. Já a operação adicionarDocente(). que faz com <transition>. que podemos <evaluate expression=”docenteController.xsd”> é criar o banco de dados. afirmam </on-render> que um “estado” é o momento durante o ciclo de vida de um <transition on=”novo” to=”form” /> objeto no qual ele satisfaz algumas condições. pronto para ser testado.springframework. até pela obviedade de troller. result da tag <evaluate> define o armazenamento do retorno do método listarDocentes() em uma variável chamada do- centeList.removerDocente(docenteId)” /> especificamente.docenteList”/>.0. assim como pelo mecanismo de o que viabilizará a inserção dos dados do formulário de cadastro injeção de dependência do Spring. <action-state id=”inserirDocenteAction”> MATRICULA VARCHAR(100). Script de criação da tabela DOCENTES. deixando a estrutura de navegação </flow> do website mais clara e. a URL http://localhost:8080/inserirDocente. No que diz respeito à estrutura do projeto.apache.org Site oficial do projeto Spring. separando toda a lógica de negócio da estruturados e. uma inovação no que diz respeito ao padrão Model-View-Controller. http://projects. volvimento orientado a objetos. Trabalha com Java há quase 20 http://www. de maneira transparente.io/spring-webflow/ Alessandro Jatobá jatoba@jatoba. no Canadá. Outra o SWF é ideal para construir aplicações web em que as regras de vantagem é a possibilidade de organizar os fluxos em subfluxos negócio demandam guiar o usuário por fluxos bem controlados. Todos os direitos reservados para DevMedia 31 . lógica de navegação. lecionando temas ligados ao desen. Doutorando em https://spring. Site oficial do Apache Maven. reusáveis. o que nos possibilita afirmar que deixar a estrutura da aplicação visível e viabilizar o reuso.org anos.io/ Engenharia também pela UFRJ com Doutorado-Sanduíche na Site oficial do Hibernate. especialmente por workflow na plataforma web.org/ Copyright . Links: Autor Site oficial do projeto Spring Web Flow.hibernate.Proibido copiar ou distribuir. o fato dos fluxos Sendo assim. Também é professor universitário. os recursos do SWF devem ser explorados de serem organizados em um arquivo XML e identificados de forma forma bastante ampla para obter um melhor gerenciamento do única constitui mais uma vantagem do SWF. a maior parte deles liderando equipes de desenvolvedores em projetos Web. https://maven. Universidade de Waterloo.spring. ocasionalmente. Mestre em Ciência da Computação pela UFRJ. Proibido copiar ou distribuir.Aprenda a utilizar o Spring Web Flow 32 Copyright . Todos os direitos reservados para DevMedia . Documents Similar To Easy-java 056 ZxcdertySkip carouselcarousel previouscarousel nextExercicios UmliconixAD2 - metodologia e projetos de softwareDiagrama de ClasseDiagrama de InteraçãoC013anliseorientadaaobjetos-100207191356-phpapp01UML_SENACpapsuml3ed-exercicios-resolvidoslivor principios.pdfSimulado NP2Revis Aot CcUML 2 - Guia PráticoDiagrama de Casos de Uso Principais Desafios Na ElaboraçãoUML E CASOS DE USOModelagem de Interações -slides - Principios de Analise e Projeto de Sistema com UML - BEZERRALista de FuncionalidadesASOO Atividade de Casa v 23 05Processo de to de SoftwareDocument or Equis i to sProva Concurso UFPE - Analista de SistemasModelagem Estática Dinâmica 01.pdfPort GrupoExercicios Bezerra (Gabarito)prova analistamonografia_Leandro1.8A2Modelando Sistemas Em UML - Casos de UsoArtigo SQL Magazine 63 - Utilizando UML_ Diagrama de ClassesLP_aula1ES - ICONIXMore From dhhiegoSkip carouselcarousel previouscarousel nextJava-magazine 105 IbrjirdyTeste2 docTeste 22222algaworks-livreto-primeiros-passos-com-spring-mvc-v1.1.pdfJava-magazine 101 EopcsgvdJava-magazine 127 SutvtoezDocumentoJAVA-MAGAZINE_105_IBRJIRDY.pdfTESTE.docxlab01.pdfspring-boot-in-action.pdflivro-bootstrap3.pdfEasy-java 052 XtygbsaqEasy-java 045 Xhaitliqlivro.txtlab01Easy-java 055 Vonbremyalgaworks-livro-spring-boot-v2.0.pdfMenu inferiorVoltar para o topoSobreSobre o ScribdImprensaNosso blogJunte-se à nossa equipe!Contate-nosEntre hojeConvidar amigosPresentesSuporteAjuda / FAQAcessibilidadeAjuda de compraAdChoicesEditorasLegalTermosPrivacidadeDireitos autoraisRedes sociaisCopyright © 2018 Scribd Inc. .Ver livros.Diretório do site.Idioma do site: English中文EspañolالعربيةPortuguês日本語DeutschFrançaisTurkceРусский языкTiếng việtJęzyk polskiBahasa indonesiaMaster your semester with Scribd & The New York TimesSpecial offer for students: Only $4.99/month.Master your semester with Scribd & The New York TimesRead Free for 30 DaysCancel anytime.Read Free for 30 DaysVocê está lendo uma amostra gratuitaBaixarClose DialogAre you sure?This action might not be possible to undo. Are you sure you want to continue?CANCELOK


Comments

Copyright © 2024 UPDOCS Inc.