From ce0b636e812d6f9eef99b856a4732b956387edc6 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 8 Apr 2024 18:37:29 +0000 Subject: [PATCH] Build .adoc Files for GitHub Pages from 92e315a4c43f0c6c22935f3d9dcc813b685eb185 --- .github/workflows/asciidoctor-ghpages.yml | 24 - README.adoc | 54 - README.html | 462 +++++++ comportamentais/01-strategy/README.adoc | 280 ----- comportamentais/01-strategy/README.html | 954 ++++++++++++++ comportamentais/01-strategy/index.html | 1 + .../01-strategy/modelagem/README.adoc | 5 - .../01-strategy/modelagem/README.html | 454 +++++++ .../01-strategy/modelagem/index.html | 1 + .../ordenar-lista-base/README.adoc | 8 - .../ordenar-lista-base/README.html | 458 +++++++ .../01-strategy/ordenar-lista-base/index.html | 1 + .../01-strategy/ordenar-lista/README.adoc | 8 - .../01-strategy/ordenar-lista/README.html | 458 +++++++ .../01-strategy/ordenar-lista/index.html | 1 + .../retorno-boleto-funcional/README.adoc | 73 -- .../retorno-boleto-funcional/README.html | 541 ++++++++ .../retorno-boleto-funcional/index.html | 1 + .../retorno-boleto-reflection/README.adoc | 36 - .../retorno-boleto-reflection/README.html | 505 ++++++++ .../retorno-boleto-reflection/index.html | 1 + .../01-strategy/retorno-boleto/README.adoc | 21 - .../01-strategy/retorno-boleto/README.html | 464 +++++++ .../01-strategy/retorno-boleto/index.html | 1 + .../slides-strategy-funcional.adoc | 39 - .../slides-strategy-funcional.html | 680 ++++++++++ comportamentais/01-strategy/slides.adoc | 177 --- comportamentais/01-strategy/slides.html | 1084 ++++++++++++++++ .../02-template-method/README.adoc | 231 ---- .../02-template-method/README.html | 806 ++++++++++++ comportamentais/02-template-method/index.html | 1 + .../02-template-method/modelagem/README.adoc | 7 - .../02-template-method/modelagem/README.html | 459 +++++++ .../02-template-method/modelagem/index.html | 1 + .../README.adoc | 18 - .../README.html | 477 +++++++ .../index.html | 1 + .../README.adoc | 21 - .../README.html | 466 +++++++ .../index.html | 1 + .../retorno-boleto-template/README.adoc | 10 - .../retorno-boleto-template/README.html | 467 +++++++ .../retorno-boleto-template/index.html | 1 + .../02-template-method/slides.adoc | 238 ---- .../02-template-method/slides.html | 1099 +++++++++++++++++ comportamentais/README.adoc | 25 - comportamentais/README.html | 488 ++++++++ comportamentais/index.html | 1 + comportamentais/observer/README.adoc | 61 - comportamentais/observer/README.html | 525 ++++++++ comportamentais/observer/index.html | 1 + criacionais/01-simple-factory/README.adoc | 222 ---- criacionais/01-simple-factory/README.html | 790 ++++++++++++ .../README.adoc | 11 - .../README.html | 468 +++++++ .../index.html | 1 + .../exportador-simple-factory/README.adoc | 12 - .../exportador-simple-factory/README.html | 469 +++++++ .../exportador-simple-factory/index.html | 1 + criacionais/01-simple-factory/index.html | 1 + .../01-simple-factory/modelagem/README.adoc | 5 - .../01-simple-factory/modelagem/README.html | 454 +++++++ .../01-simple-factory/modelagem/index.html | 1 + .../README.adoc | 19 - .../README.html | 476 +++++++ .../index.html | 1 + .../retorno-boleto-simple-factory/README.adoc | 12 - .../retorno-boleto-simple-factory/README.html | 468 +++++++ .../retorno-boleto-simple-factory/index.html | 1 + criacionais/01-simple-factory/slides.adoc | 188 --- criacionais/01-simple-factory/slides.html | 1000 +++++++++++++++ criacionais/02-factory-method/README.adoc | 124 -- criacionais/02-factory-method/README.html | 650 ++++++++++ .../README.adoc | 12 - .../README.html | 468 +++++++ .../index.html | 1 + .../README.adoc | 20 - .../README.html | 478 +++++++ .../index.html | 1 + criacionais/02-factory-method/index.html | 1 + .../02-factory-method/modelagem/README.adoc | 5 - .../02-factory-method/modelagem/README.html | 454 +++++++ .../02-factory-method/modelagem/index.html | 1 + criacionais/02-factory-method/slides.adoc | 145 --- criacionais/02-factory-method/slides.html | 930 ++++++++++++++ criacionais/03-singleton/README.adoc | 115 -- criacionais/03-singleton/README.html | 637 ++++++++++ .../config-singleton-spring/README.adoc | 3 - .../config-singleton-spring/README.html | 452 +++++++ .../config-singleton-spring/index.html | 1 + criacionais/03-singleton/index.html | 1 + .../03-singleton/modelagem/README.adoc | 3 - .../03-singleton/modelagem/README.html | 452 +++++++ criacionais/03-singleton/modelagem/index.html | 1 + criacionais/03-singleton/slides.adoc | 117 -- criacionais/03-singleton/slides.html | 874 +++++++++++++ criacionais/04-builder/README.adoc | 160 --- criacionais/04-builder/README.html | 750 +++++++++++ criacionais/04-builder/index.html | 1 + .../README.adoc | 22 - .../README.html | 463 +++++++ .../index.html | 1 + .../README.adoc | 28 - .../README.html | 469 +++++++ .../index.html | 1 + .../paciente-builder-base/README.adoc | 18 - .../paciente-builder-base/README.html | 461 +++++++ .../paciente-builder-base/index.html | 1 + criacionais/04-builder/slides.adoc | 212 ---- criacionais/04-builder/slides.html | 829 +++++++++++++ criacionais/README.adoc | 27 - criacionais/README.html | 494 ++++++++ criacionais/index.html | 1 + estruturais/01-adapter/README.adoc | 140 --- estruturais/01-adapter/README.html | 682 ++++++++++ .../captcha-adapters-v1/README.adoc | 19 - .../captcha-adapters-v1/README.html | 464 +++++++ .../01-adapter/captcha-adapters-v1/index.html | 1 + .../README.adoc | 21 - .../README.html | 467 +++++++ .../index.html | 1 + .../README.adoc | 22 - .../README.html | 477 +++++++ .../index.html | 1 + .../README.adoc | 17 - .../README.html | 468 +++++++ .../index.html | 1 + estruturais/01-adapter/index.html | 1 + estruturais/01-adapter/modelagem/README.adoc | 10 - estruturais/01-adapter/modelagem/README.html | 460 +++++++ estruturais/01-adapter/modelagem/index.html | 1 + estruturais/01-adapter/slides.adoc | 151 --- estruturais/01-adapter/slides.html | 958 ++++++++++++++ estruturais/README.adoc | 22 - estruturais/README.html | 473 +++++++ estruturais/decorator/README.adoc | 74 -- estruturais/decorator/README.html | 574 +++++++++ estruturais/decorator/index.html | 1 + estruturais/facade/README.adoc | 47 - estruturais/facade/README.html | 506 ++++++++ .../facade/cotacao-bolsa-valores/README.adoc | 30 - .../facade/cotacao-bolsa-valores/README.html | 477 +++++++ .../facade/cotacao-bolsa-valores/index.html | 1 + estruturais/facade/index.html | 1 + estruturais/index.html | 1 + exercicios/README.adoc | 25 - exercicios/README.html | 484 ++++++++ exercicios/calculo-desconto/README.adoc | 30 - exercicios/calculo-desconto/README.html | 502 ++++++++ exercicios/calculo-desconto/index.html | 1 + exercicios/envio-mensagens/README.adoc | 32 - exercicios/envio-mensagens/README.html | 505 ++++++++ exercicios/envio-mensagens/index.html | 1 + exercicios/imposto-renda/README.adoc | 47 - exercicios/imposto-renda/README.html | 508 ++++++++ exercicios/imposto-renda/index.html | 1 + exercicios/index.html | 1 + exercicios/instanciar-produtos/README.adoc | 45 - exercicios/instanciar-produtos/README.html | 544 ++++++++ exercicios/instanciar-produtos/index.html | 1 + exercicios/random-numbers/README.adoc | 62 - exercicios/random-numbers/README.html | 535 ++++++++ exercicios/random-numbers/index.html | 1 + .../real-random-number-services/README.adoc | 107 -- .../real-random-number-services/README.html | 629 ++++++++++ .../real-random-number-services/index.html | 1 + index.html | 1 + links.adoc | 22 - links.html | 514 ++++++++ plano-ensino-padroes-projetos.adoc | 68 - plano-ensino-padroes-projetos.html | 602 +++++++++ 171 files changed, 34712 insertions(+), 3807 deletions(-) delete mode 100644 .github/workflows/asciidoctor-ghpages.yml delete mode 100644 README.adoc create mode 100644 README.html delete mode 100644 comportamentais/01-strategy/README.adoc create mode 100644 comportamentais/01-strategy/README.html create mode 120000 comportamentais/01-strategy/index.html delete mode 100755 comportamentais/01-strategy/modelagem/README.adoc create mode 100644 comportamentais/01-strategy/modelagem/README.html create mode 120000 comportamentais/01-strategy/modelagem/index.html delete mode 100755 comportamentais/01-strategy/ordenar-lista-base/README.adoc create mode 100644 comportamentais/01-strategy/ordenar-lista-base/README.html create mode 120000 comportamentais/01-strategy/ordenar-lista-base/index.html delete mode 100755 comportamentais/01-strategy/ordenar-lista/README.adoc create mode 100644 comportamentais/01-strategy/ordenar-lista/README.html create mode 120000 comportamentais/01-strategy/ordenar-lista/index.html delete mode 100644 comportamentais/01-strategy/retorno-boleto-funcional/README.adoc create mode 100644 comportamentais/01-strategy/retorno-boleto-funcional/README.html create mode 120000 comportamentais/01-strategy/retorno-boleto-funcional/index.html delete mode 100755 comportamentais/01-strategy/retorno-boleto-reflection/README.adoc create mode 100644 comportamentais/01-strategy/retorno-boleto-reflection/README.html create mode 120000 comportamentais/01-strategy/retorno-boleto-reflection/index.html delete mode 100755 comportamentais/01-strategy/retorno-boleto/README.adoc create mode 100644 comportamentais/01-strategy/retorno-boleto/README.html create mode 120000 comportamentais/01-strategy/retorno-boleto/index.html delete mode 100644 comportamentais/01-strategy/slides-strategy-funcional.adoc create mode 100644 comportamentais/01-strategy/slides-strategy-funcional.html delete mode 100644 comportamentais/01-strategy/slides.adoc create mode 100644 comportamentais/01-strategy/slides.html delete mode 100755 comportamentais/02-template-method/README.adoc create mode 100644 comportamentais/02-template-method/README.html create mode 120000 comportamentais/02-template-method/index.html delete mode 100755 comportamentais/02-template-method/modelagem/README.adoc create mode 100644 comportamentais/02-template-method/modelagem/README.html create mode 120000 comportamentais/02-template-method/modelagem/index.html delete mode 100755 comportamentais/02-template-method/retorno-boleto-template-funcional/README.adoc create mode 100644 comportamentais/02-template-method/retorno-boleto-template-funcional/README.html create mode 120000 comportamentais/02-template-method/retorno-boleto-template-funcional/index.html delete mode 100755 comportamentais/02-template-method/retorno-boleto-template-strategy/README.adoc create mode 100644 comportamentais/02-template-method/retorno-boleto-template-strategy/README.html create mode 120000 comportamentais/02-template-method/retorno-boleto-template-strategy/index.html delete mode 100755 comportamentais/02-template-method/retorno-boleto-template/README.adoc create mode 100644 comportamentais/02-template-method/retorno-boleto-template/README.html create mode 120000 comportamentais/02-template-method/retorno-boleto-template/index.html delete mode 100644 comportamentais/02-template-method/slides.adoc create mode 100644 comportamentais/02-template-method/slides.html delete mode 100644 comportamentais/README.adoc create mode 100644 comportamentais/README.html create mode 120000 comportamentais/index.html delete mode 100755 comportamentais/observer/README.adoc create mode 100644 comportamentais/observer/README.html create mode 120000 comportamentais/observer/index.html delete mode 100755 criacionais/01-simple-factory/README.adoc create mode 100644 criacionais/01-simple-factory/README.html delete mode 100755 criacionais/01-simple-factory/exportador-simple-factory-reflection/README.adoc create mode 100644 criacionais/01-simple-factory/exportador-simple-factory-reflection/README.html create mode 120000 criacionais/01-simple-factory/exportador-simple-factory-reflection/index.html delete mode 100755 criacionais/01-simple-factory/exportador-simple-factory/README.adoc create mode 100644 criacionais/01-simple-factory/exportador-simple-factory/README.html create mode 120000 criacionais/01-simple-factory/exportador-simple-factory/index.html create mode 120000 criacionais/01-simple-factory/index.html delete mode 100755 criacionais/01-simple-factory/modelagem/README.adoc create mode 100644 criacionais/01-simple-factory/modelagem/README.html create mode 120000 criacionais/01-simple-factory/modelagem/index.html delete mode 100755 criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/README.adoc create mode 100644 criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/README.html create mode 120000 criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/index.html delete mode 100755 criacionais/01-simple-factory/retorno-boleto-simple-factory/README.adoc create mode 100644 criacionais/01-simple-factory/retorno-boleto-simple-factory/README.html create mode 120000 criacionais/01-simple-factory/retorno-boleto-simple-factory/index.html delete mode 100755 criacionais/01-simple-factory/slides.adoc create mode 100644 criacionais/01-simple-factory/slides.html delete mode 100644 criacionais/02-factory-method/README.adoc create mode 100644 criacionais/02-factory-method/README.html delete mode 100755 criacionais/02-factory-method/exportador-factory-method-reflection/README.adoc create mode 100644 criacionais/02-factory-method/exportador-factory-method-reflection/README.html create mode 120000 criacionais/02-factory-method/exportador-factory-method-reflection/index.html delete mode 100755 criacionais/02-factory-method/exportador-problematico-generic/README.adoc create mode 100644 criacionais/02-factory-method/exportador-problematico-generic/README.html create mode 120000 criacionais/02-factory-method/exportador-problematico-generic/index.html create mode 120000 criacionais/02-factory-method/index.html delete mode 100755 criacionais/02-factory-method/modelagem/README.adoc create mode 100644 criacionais/02-factory-method/modelagem/README.html create mode 120000 criacionais/02-factory-method/modelagem/index.html delete mode 100644 criacionais/02-factory-method/slides.adoc create mode 100644 criacionais/02-factory-method/slides.html delete mode 100755 criacionais/03-singleton/README.adoc create mode 100644 criacionais/03-singleton/README.html delete mode 100644 criacionais/03-singleton/config-singleton-spring/README.adoc create mode 100644 criacionais/03-singleton/config-singleton-spring/README.html create mode 120000 criacionais/03-singleton/config-singleton-spring/index.html create mode 120000 criacionais/03-singleton/index.html delete mode 100755 criacionais/03-singleton/modelagem/README.adoc create mode 100644 criacionais/03-singleton/modelagem/README.html create mode 120000 criacionais/03-singleton/modelagem/index.html delete mode 100755 criacionais/03-singleton/slides.adoc create mode 100644 criacionais/03-singleton/slides.html delete mode 100644 criacionais/04-builder/README.adoc create mode 100644 criacionais/04-builder/README.html create mode 120000 criacionais/04-builder/index.html delete mode 100755 criacionais/04-builder/paciente-builder-automatico-immutables/README.adoc create mode 100644 criacionais/04-builder/paciente-builder-automatico-immutables/README.html create mode 120000 criacionais/04-builder/paciente-builder-automatico-immutables/index.html delete mode 100755 criacionais/04-builder/paciente-builder-automatico-lombok/README.adoc create mode 100644 criacionais/04-builder/paciente-builder-automatico-lombok/README.html create mode 120000 criacionais/04-builder/paciente-builder-automatico-lombok/index.html delete mode 100755 criacionais/04-builder/paciente-builder-base/README.adoc create mode 100644 criacionais/04-builder/paciente-builder-base/README.html create mode 120000 criacionais/04-builder/paciente-builder-base/index.html delete mode 100644 criacionais/04-builder/slides.adoc create mode 100644 criacionais/04-builder/slides.html delete mode 100644 criacionais/README.adoc create mode 100644 criacionais/README.html create mode 120000 criacionais/index.html delete mode 100644 estruturais/01-adapter/README.adoc create mode 100644 estruturais/01-adapter/README.html delete mode 100644 estruturais/01-adapter/captcha-adapters-v1/README.adoc create mode 100644 estruturais/01-adapter/captcha-adapters-v1/README.html create mode 120000 estruturais/01-adapter/captcha-adapters-v1/index.html delete mode 100644 estruturais/01-adapter/captcha-adapters-v2-template-method/README.adoc create mode 100644 estruturais/01-adapter/captcha-adapters-v2-template-method/README.html create mode 120000 estruturais/01-adapter/captcha-adapters-v2-template-method/index.html delete mode 100755 estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/README.adoc create mode 100644 estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/README.html create mode 120000 estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/index.html delete mode 100644 estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/README.adoc create mode 100644 estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/README.html create mode 120000 estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/index.html create mode 120000 estruturais/01-adapter/index.html delete mode 100644 estruturais/01-adapter/modelagem/README.adoc create mode 100644 estruturais/01-adapter/modelagem/README.html create mode 120000 estruturais/01-adapter/modelagem/index.html delete mode 100644 estruturais/01-adapter/slides.adoc create mode 100644 estruturais/01-adapter/slides.html delete mode 100644 estruturais/README.adoc create mode 100644 estruturais/README.html delete mode 100755 estruturais/decorator/README.adoc create mode 100644 estruturais/decorator/README.html create mode 120000 estruturais/decorator/index.html delete mode 100644 estruturais/facade/README.adoc create mode 100644 estruturais/facade/README.html delete mode 100644 estruturais/facade/cotacao-bolsa-valores/README.adoc create mode 100644 estruturais/facade/cotacao-bolsa-valores/README.html create mode 120000 estruturais/facade/cotacao-bolsa-valores/index.html create mode 120000 estruturais/facade/index.html create mode 120000 estruturais/index.html delete mode 100755 exercicios/README.adoc create mode 100644 exercicios/README.html delete mode 100755 exercicios/calculo-desconto/README.adoc create mode 100644 exercicios/calculo-desconto/README.html create mode 120000 exercicios/calculo-desconto/index.html delete mode 100755 exercicios/envio-mensagens/README.adoc create mode 100644 exercicios/envio-mensagens/README.html create mode 120000 exercicios/envio-mensagens/index.html delete mode 100755 exercicios/imposto-renda/README.adoc create mode 100644 exercicios/imposto-renda/README.html create mode 120000 exercicios/imposto-renda/index.html create mode 120000 exercicios/index.html delete mode 100755 exercicios/instanciar-produtos/README.adoc create mode 100644 exercicios/instanciar-produtos/README.html create mode 120000 exercicios/instanciar-produtos/index.html delete mode 100755 exercicios/random-numbers/README.adoc create mode 100644 exercicios/random-numbers/README.html create mode 120000 exercicios/random-numbers/index.html delete mode 100644 exercicios/real-random-number-services/README.adoc create mode 100644 exercicios/real-random-number-services/README.html create mode 120000 exercicios/real-random-number-services/index.html create mode 120000 index.html delete mode 100644 links.adoc create mode 100644 links.html delete mode 100644 plano-ensino-padroes-projetos.adoc create mode 100644 plano-ensino-padroes-projetos.html diff --git a/.github/workflows/asciidoctor-ghpages.yml b/.github/workflows/asciidoctor-ghpages.yml deleted file mode 100644 index 4a9eb5c00..000000000 --- a/.github/workflows/asciidoctor-ghpages.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: asciidoctor-ghpages - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - # This workflow contains a single job called "build" - build: - # The type of runner that the job will run on - runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - - name: asciidoctor-ghpages - uses: manoelcampos/asciidoctor-ghpages-action@v2 diff --git a/README.adoc b/README.adoc deleted file mode 100644 index c803d1d75..000000000 --- a/README.adoc +++ /dev/null @@ -1,54 +0,0 @@ -:source-highlighter: highlightjs -:allow-uri-read: -:safe: unsafe -:numbered: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -:toc: left - -= Padrões de Projeto em Java -Prof. Manoel Campos da Silva Filho - -ifdef::env-github[] - -image:https://github.com/manoelcampos/padroes-projetos/workflows/asciidoctor-ghpages/badge.svg[GitHub Pages,link=http://manoelcampos.com/padroes-projetos/] - -[IMPORTANT] -==== -- Se você não pretende fazer alterações neste repositório, não faça fork. Se fizer, sempre que o projeto for atualizado, sua cópia vai ficar absoleta. Se você quer apenas baixar para navegar localmente, faça um clone no botão `Code` acima. -- Se você quer apenas salvar o projeto para consulta posterior, use o botão `Star` ⭐️ acima. Isto ainda ajuda a divulgar o material. -==== -endif::[] - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: - -Uma apresentação sobre como chegamos aos padrões de projetos e a importância deles pode ser https://docs.google.com/presentation/d/1zEIB-XPI8Icgb7sX8gCofHfMmaEB3D7eV-A_eiT90bc[acessada aqui]. - -== Categorias de Padrões - -- link:comportamentais[Padrões Comportamentais] -- link:criacionais[Padrões Criacionais] -- link:estruturais[Padrões Estruturais] - -== Exercícios - -Na página de cada padrão normalmente há alguns exercícios, -mas uma lista adicional está link:exercicios[disponível aqui]. - -== Material Complementar - -Links para materais complementares estão disponíveis na https://github.com/manoelcampos/padroes-projetos/wiki[Wiki]. diff --git a/README.html b/README.html new file mode 100644 index 000000000..31033bd8c --- /dev/null +++ b/README.html @@ -0,0 +1,462 @@ + + + + + + + + +Padrões de Projeto em Java + + + + + + +
+ +
+ + + + + \ No newline at end of file diff --git a/comportamentais/01-strategy/README.adoc b/comportamentais/01-strategy/README.adoc deleted file mode 100644 index e84a42dc8..000000000 --- a/comportamentais/01-strategy/README.adoc +++ /dev/null @@ -1,280 +0,0 @@ -:imagesdir: ../../images/patterns/strategy -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Comportamentais - -== Strategy (Estratégia) - -NOTE: https://youtu.be/uQltGzH3Hms[Vídeo de apresentação do padrão] - -=== Definição - -// tag::definicao[] -📘"O padrão Strategy define uma família de algoritmos, encapsula cada um deles e os torna intercambiáveis. A estratégia deixa o algoritmo variar independentemente dos clientes que o utilizam" <>. -// end::definicao[] - -Em outras palavras, a partir de um conjunto de algoritmos, permite que classes possam trocar tais algoritmos por uma outra implementação, até mesmo em tempo de execução. - -=== Aplicabilidade - -Pode ser aplicado quando: - -// tag::aplicabilidade[] -- o comportamento de um método (implementação de um algoritmo) precisa ser diferente em classes distintas e/ou mudar em tempo de execução; -- determinadas classes devem ter um comportamento específico (método) e outras não; -- não deseja-se que uma alteração em uma super classe afete sub classes. -// end::aplicabilidade[] - -=== Modelagem do Padrão - -image::strategy-base-class-diagram.png[] - -A classe `Estrategista` é que que irá usar as estratégias, que são representadas pelas classes que implementam os comportamentos. -Cada comportamento (estratégia) é normalmente definido como uma interface. Assim, podem existir N implementações de cada comportamento (diferentes estratégias). - -Perceba que a relação entre a `Estrategista` e os comportamentos não é herança, mas pode ser uma associação normal, composição ou agregação. Cada comportamento não é implementado como uma subclasse da `Estrategista`, cada tipo de comportamento estará contido como um atributo dentro da `Estrategista`. Por isso é comum representar como agregação/composição. Definindo o comportamento como atributo é que nos permite alterar em tempo de execução sua implementação. - -O comportamento em si é definido por um método na interface. No exemplo, o método é `executarComportamentoA()` para o `ComportamentoA`. O nome do método é o desenvolvedor quem define, normalmente sendo um nome que faça sentido para o sistema. -A assinatura do método também é livre. Neste exemplo o método não recebe parâmetros e retorna um tipo genérico `T`. O tipo do retorno vai depender das suas necessidades. Veja os exemplos concretos na seção a seguir. - -Podem existir diferentes classes filhas desta `Estrategista`, cada uma fazendo uso diferente do resultado de um determinado comportamento. -Com o padrão Strategy, o comportamento de qualquer classe (mãe ou filha) pode mudar em tempo de execução, de acordo com os requisitos do sistema. - -Um projeto de exemplo para o diagrama apresentado está disponível link:modelagem[aqui]. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão. - -=== Princípios utilizados - -- https://en.wikipedia.org/wiki/Composition_over_inheritance[Favorecer composição no lugar de herança]. -- https://tuhrig.de/programming-to-an-interface/[Programar para uma "interface" não uma implementação] (GoF): declaramos variáveis com tipos abstratos (uma interface de comportamento) e usamos tipos concretos (uma classe que implementa um comportamento) apenas na instanciação. -- https://en.wikipedia.org/wiki/Single_responsibility_principle[Single Responsibility Principle (SRP)] pois a classe que usa os comportamentos não tem a responsabilidade de implementar estes comportamentos. Adicionalmente, cada classe de comportamento é responsável por implementar um único comportamento. Se temos vários comportamentos, devemos ter várias classes. -- https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)], pois separa as partes que mudam (os comportamentos) de dentro da classe que utiliza eles. Isto torna a classe "aberta para extensão e fechada para modificação" (em relação aos comportamentos). -- https://en.wikipedia.org/wiki/Liskov_substitution_principle[Liskov Substitution Principle (LSP)] pois podemos substituir um comportamento por qualquer implementação dele, de forma transparente, até mesmo em tempo de execução, sem que sejam necessárias alterações no código interno da classe que utiliza tais comportamentos. -- https://en.wikipedia.org/wiki/Interface_segregation_principle[Interface Segregation Principle (ISP)], pois estamos definindo diferentes interfaces: uma para cada comportamento que pode ser implementado. - - -=== Exemplos - -pass:[] - -==== Leitura de arquivos de retorno de boletos bancários. - -Arquivos de retorno são enviados pelos bancos às empresas, fornecendo uma lista de boletos -pagos por clientes, para que tais empresas possam registrar o pagamento desses boletos -em seus sistemas. Os bancos utilizam um arquivo de texto com campos de comprimento fixo, onde não existe um caractere delimitador. Cada campo tem uma quantidade fixa de caracteres. Se o valor possui menos caracteres do que deveria, o tamanho é completado com espaços em branco. - -Um aplicação na empresa recebedora dos boletos deve ler tais arquivos para extrair os dados -e normalmente gravar em um banco de dados. Existem diferentes formatos para tais arquivos -e cada banco pode utilizar um formato diferente. Atualmente existem inúmeros projetos em diferentes linguagens para fazer a leitura de tais arquivos, /retorno-boletophp[como este]. Vamos implementar um solução simplificada aqui apenas para efeitos didáticos. - -NOTE: Apesar de atualmente termos formatos de arquivos mais utilizados como JSON e XML, formatos como o mencionado ainda são bastante utilizados, principalmente no meio acadêmico, por serem simples. Um outro exemplo de tais formatos são os arquivos https://pt.wikipedia.org/wiki/Comma-separated_values[CSV]. Mas em aplicações Web e mobile, o mais comum é o uso de JSON e XML. - -Para este exemplo, vamos considerar que o Banco do Brasil usa um tipo de arquivo onde cada linha com as informações sobre o pagamento de um boleto contém os seguintes campos, separados por ponto-e-vírgula: - -// tag::campos-boleto1[] -1. id do boleto com 10 dígitos -2. código do banco onde o boleto foi pago (3 dígitos) -3. data vencimento (dd/mm/yyyy) -4. data pagamento (dd/mm/yyyy) -5. CPF do cliente (sem . e -) -6. valor do boleto (decimal 10.2) -7. multa por atraso (decimal 10.2) -8. juros no formato (decimal 10.2) -// end::campos-boleto1[] - -Mas digamos que você também precisa receber arquivos do Bradesco que possui o seguinte formato: - -1. id do boleto com 10 dígitos -2. cód banco onde o boleto foi pago (3 dígitos) -// tag::campos-boleto2[] -3. *agência onde o boleto foi pago (6 dígitos) -4. *conta do cliente para possível estorno de pagamento (9 dígitos) -5. data vencimento (dd/mm/yyyy) -6. *data/hora pagamento (dd/mm/yyyy hh:nn:ss) -7. *CPF do cliente (com . e -) -8. valor do boleto (decimal 10.2) -9. multa por atraso (decimal 10.2) -10. juros no formato (decimal 10.2) -// end::campos-boleto2[] - -*__Campos adicionais ou diferentes do formato anterior.__ - -Um diagrama de classes para tal implementação pode ser como abaixo. - -image:retorno-boleto-class-diagram.png[] - -O código fonte com uma implementação de exemplo pode ser obtido link:retorno-boleto[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/strategy/retorno-boleto[zip]). -Tente primeiro fazer sua implementação a partir da leitura do diagrama, -para depois analisar o código disponibilizado. - -NOTE: Uma implementação em Node.js está disponível em link:javascript/retorno-boleto-js[retorno-boleto-js]. - -=== Detalhes de Implementação - -Mesmo que uma classe não tenha um determinado comportamento, como o definido pela interface `ComportamentoA`, haverá uma associação entre a classe e o comportamento. -Se a classe não precisar de uma implementação de tal comportamento, o atributo que representa a associação pode estar nulo. Ao tentar usar o comportamento é gerada a exceção `NullPointerException`. - -Para resolver isso, podemos criar uma classe que tenha uma implementação vazia para o comportamento, ou seja, que não faz nada. Isto normalmente pode ser implementado pelo padrão Null Object que veremos posteriormente. - -Se a classe estrategista é obrigada a ter um determinado comportamento, -para evitar `NullPointerException`, podemos não incluir um construtor sem parâmetros e incluir um que exija uma implementação de estratégia a ser usada. - -pass:[] - -== Modelagem Convencional sem o padrão Strategy 🤔 - -A modelagem convencional de diferentes comportamentos sem a aplicação do padrão Strategy requer o uso de herança para os diferentes comportamentos e é visualmente mais simples. -No entanto, tal implementação tem algumas características que podem ser um problema (ou não), dependendo dos requisitos do seu sistema, por não permitir: - -- alterar um comportamento em tempo de execução; -- compartilhar implementações de um mesmo comportamento entre diferentes classes filhas, levando à duplicação de código (que deve ser evitado ao máximo); -- combinar comportamentos distintos em um só, reaproveitando código. - -image:no-strategy-class-diagram.png[] - -== Como **NÃO** implementar uma solução para um problema 😳 - -Se o padrão não for aplicado nem a solução com herança acima, uma outra solução normalmente é implementada por meio de uma única classe. Não será mostrado nem mesmo um diagrama, pois a solução seria composta de fato apenas por uma classe. Ela então teria métodos como `T executarComportamentoA()`. Todas as implementações deste "Comportamento A" seriam incluídas no método citado. - -Para o exemplo do retorno de boletos bancários, isto significa que tal método seria algo como: - -// tag::como-nao-implementar[] -[source,java] ----- -public void processar(String nomeArquivo){ - if(nomeArquivo.contains("banco-brasil")){ - //processa arquivo do Banco do Brasil - } - else if(nomeArquivo.contains("bradesco")){ - //processa arquivo do Bradesco - } -} ----- -// end::como-nao-implementar[] - -Tal código é extremamente mais simples, tem uma única classe e tudo é feito em um único método. -Apesar de parecer muito melhor por simplificar as coisas e dar a impressão que estamos usando o princípio https://pt.wikipedia.org/wiki/Princípio_KISS[KISS], não chamaria esta solução de simples, mas simplista e ingênua. **Soluções simplistas normalmente vão lhe trazer dores de cabeça para manutenção do software**. -Por isto, esta "solução" *é totalmente não recomendada*. - -Considerando que podemos ter diferentes formatos de arquivos para bancos distintos e que precisamos processar arquivos de vários bancos, esta solução apresenta alguns problemas. O método `processar`: - -- vai ficar longo e possivelmente confuso; -- não tem uma única responsabilidade (viola o princípio https://en.wikipedia.org/wiki/Single_responsibility_principle[SRP]), pois ele processa arquivos de diferentes bancos, no lugar de processar arquivos de um banco específico; -- cada vez que um novo banco precisar ser incluído, o código precisará ser alterado (viola o princípio https://en.wikipedia.org/wiki/Open–closed_principle[OCP]). - -O problema da violação do OCP é o mais problemático aqui. O uso de _if's_ (ou qualquer estrutura condicional como `switch`) para decidir qual algoritmo será executado em cada situação deixa claro que uma nova condição precisará ser adicionada sempre que um novo banco precisar ser suportado. Se em outros lugares do sistema você precisa realizar outras tarefas com estes arquivos de retorno, tende-se a repetir esta mesma cadeia de _if's_. -Por exemplo, se em um lugar do sistema você precisa processar os arquivos e incluir os dados em um banco de dados e em outro você precisa processar e gerar PDFs com comprovantes de pagamentos ou enviar emails de notificação, em cada um desses locais você precisará deste bloco de _if's_. -O problema surge quando você precisar incluir um novo banco e tiver que incluir um novo _if_ em cada um desses locais. -Você pode simplesmente esquecer de adicionar tal _if_ em todos os locais necessários e o recurso funcionar em parte do sistema e em outras partes não. - -pass:[] - -== Modelagem do Padrão utilizando Programação Funcional - -[NOTE] -==== -- https://docs.google.com/presentation/d/e/2PACX-1vTJE9Dt23OdsfZda7mBuinRpy8BldyKlxfVbXalwZb2L4BFqVkkpb8SWBdIeWBhdfbl3RLOTv8J60Nd/pub?start=false&loop=false&delayms=3000[Apresentação e vídeo de introdução à programação funcional.] -- https://youtu.be/hsRbUGTV2ok[Vídeo da implementação com programação funcional.] -==== - -Observando o diagrama base para a implementação do padrão Strategy, pode-se perceber que são criadas muitas classes e interfaces. As classes implementando essas interfaces não possuem atributos e têm apenas um único método que representa a implementação da estratégia em si. - -Graças à Programação Funcional em diversas linguagens como Java 8+, JavaScript, Phython e outras, podemos simplificar este diagrama, e consequentemente a implementação, como mostra a figura a seguir. - -image:strategy-base-funcional-class-diagram.png[] - -Observe que não temos mais as interfaces e classes específicas dos comportamentos. Cada comportamento nada mais é do que a implementação de um método (como o `executarComportamentoA()` do primeiro diagrama). O que precisamos de fato é permitir a troca da implementação de tal método em tempo de execução. Mas para isso, usando Programação Orientada a Objetos, tivemos que primeiro criar um conjunto de classes e interfaces pra isso. - -Usando Programação Funcional podemos armazenar uma função em uma variável, no lugar de ter que armazenar um objeto inteiro que possui apenas um único método. A partir de tal variável, podemos então chamar a função. Se uma nova função for atribuída a tal variável, quando usarmos a variável novamente, estaremos chamando esta nova função, como espera-se que o padrão Strategy funcione. - -No diagrama, o atributo como `comportamentoA` é do tipo `Function`, uma interface do Java 8+ (dentro muitas outras) que indica que o atributo contém uma referência para um método que a classe pode chamar, no lugar de armazenar um dado primitivo ou objeto convencional. Sendo que a referência para o método está armazenada em um atributo, se tivermos um método como o `comportamentoA1` mostrado no primeiro diagrama, podemos armazenar uma referência para tal método no atributo `comportamentoA`. -Se precisarmos fazer a super classe ou qualquer subclasse usar um comportamento diferente, podemos atribuir, por exemplo, o método `comportamentoA2` ao atributo `comportamentoA` em tempo de execução. - -`Function` é uma das interfaces em Java 8+ que permite representar métodos isolados e armazenar referências deles em variáveis. -Estas são chamadas de interfaces funcionais. Lembre-se que interfaces são como tipos. Assim como uma variável do tipo `int` indica que somente números inteiros podem ser armazenados nela, uma interface funcional indica o tipo de métodos que podem ser atribuídos a uma variável de tal tipo. -Em outras palavras, tais interfaces indicam que assinatura um método deve ter para ser possível atribuí-lo a uma variável cujo tipo é uma interface funcional. - -Uma variável `Function` indica que podemos atribuir a ela qualquer método que receba um único parâmetro e retorne um determinado valor. -Se voltarmos ao exemplo dos boletos, a assinatura do nosso método que implementa os comportamentos de leitura dos arquivos de retorno é: - -[source,java] ----- -List lerArquivo(String nomeArquivo) ----- - -Observe que tal função/método recebe um parâmetro (neste caso `String`) e retorna um valor (`List`). -Assim, uma função como `lerArquivo` pode então ser atribuída a uma variável do tipo `Function`. -Se você tiver um método com uma assinatura diferente e precisar armazenar tal método em um variável, -justamente para permitir trocar a implementação de tal método em tempo de execução usando Programação Funcional, -um ponto de partida é estudar a documentação do pacote https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html[java.util.function] que descreve as interfaces funcionais padrões do Java 8+. - -Programação funcional é um assunto bastante extenso que poderia ser um curso totalmente a parte, -que envolve muitos conceitos novos. Existe muito material disponível na internet. -Mas é difícil encontrar material gratuito, em português e abrangentes. -Existe muito material em inglês, mas novamente espalhado pela web. -Se desejarem aprofundar no assunto, acessem esta https://github.com/manoelcampos/sistemas-distribuidos/tree/master/projects/00-programacao-funcional[página]. - -O código fonte do projeto usando programação funcional está disponível link:retorno-boleto-funcional[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/strategy/retorno-boleto-funcional[zip]). - -NOTE: Em linguagens distintas, a forma de implementar o padrão Strategy usando programação funcional é diferente. - -== Padrões Relacionados - -Padrões que possuem similaridades ou podem ser usados em conjunto: - -- link:../template-method[Template Method] - -== Onde o padrão é usado no JDK - -Um forma de identificar a aplicação do padrão Strategy nas classes do JDK que você usa é quando um método *requer uma interface que possui apenas um método a ser implementado*. Estas são chamadas de interfaces funcionais a partir do Java 8 (que possivelmente estão anotadas com `@FunctionalInterface`). A implementação de tal interface não é fornecida pelo JDK mas por você. -Você deve então fornecer um algoritmo (função) que será executado pela classe que estiver utilizando o padrão. - -=== List.sort(Comparator comparator) - -Tal método da interface List permite ordenar os valores dentra da lista. -`Comparator` é uma interface cujas implementações representam as estratégias de ordenação de uma lista. `Comparator` é uma interface funcional, logo, conseguimos usar programação funcional para implementar as estratégias apenas criando-se funções. Assim, não temos que obrigatoriamente criar uma classe para cada estratégia. Como podemos implementar ordenação de uma infinidade de maneiras como: - -- por ordem alfabética crescente ou descrescente; -- utilizando algoritmos mais ou menos eficientes como Bubble Sort, Shell Sort, Quick Sort, etc - -usar o padrão Strategy aqui faz todo o sentido. Podemos inclusive em um momento ordenar -uma lista de uma maneira e posteriormente decidirmos que queremos ordenar de outra maneira. - -== Exercícios - -=== Descontos - -Considere que temos um sistema de vendas onde diferentes formas de desconto podem ser implementadas de acordo as promoções vigentes, como em datas comemorativas. O sistema deve permitir o cálculo do desconto sobre a venda das seguintes maneiras: - -- percentual de desconto definido (que pode vir de um banco de dados); -- percentual de desconto progressivo: `valor da compra/25`, não podendo ultrapassar 20%; -- desconto de 15% na data de aniversário do cliente; -// - desconto de 20% no segundo item do mesmo produto. - -E como poderíamos implementar estes tipos de desconto sem utilizar Padrões de Projetos? -Quais os problemas que tal implementação traria? - -=== Ordenação de Listas - -Ordenar uma lista de estudantes utilizando programação funcional no Java 8+. -O projeto disponível link:ordenar-lista-base[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/strategy/ordenar-lista-base[zip]) pode ser usado como base, pois ele gera uma lista de estudantes aleatoriamente. - -=== Diferenças da implementação puramente OO vs funcional - -A página inicial do link:retorno-boleto-funcional[projeto funcional disponível aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/strategy/retorno-boleto-funcional[zip]) apresenta algumas diferenças -de implementação do padrão Strategy utilizando puramente programação orientada a objetos e outra versão -utilizando programação funcional. - -Descreva em detalhes qual a diferença em utilizar um atributo do tipo `LeituraRetorno` na implementação puramente OO -e um atributo do tipo `Function` na implementação funcional. diff --git a/comportamentais/01-strategy/README.html b/comportamentais/01-strategy/README.html new file mode 100644 index 000000000..ba14d3d25 --- /dev/null +++ b/comportamentais/01-strategy/README.html @@ -0,0 +1,954 @@ + + + + + + + +Padrões de Projetos Comportamentais + + + + + + + +
+
+

1. Strategy (Estratégia)

+
+ +
+

1.1. Definição

+
+

📘"O padrão Strategy define uma família de algoritmos, encapsula cada um deles e os torna intercambiáveis. A estratégia deixa o algoritmo variar independentemente dos clientes que o utilizam" [UCPP].

+
+
+

Em outras palavras, a partir de um conjunto de algoritmos, permite que classes possam trocar tais algoritmos por uma outra implementação, até mesmo em tempo de execução.

+
+
+
+

1.2. Aplicabilidade

+
+

Pode ser aplicado quando:

+
+
+
    +
  • +

    o comportamento de um método (implementação de um algoritmo) precisa ser diferente em classes distintas e/ou mudar em tempo de execução;

    +
  • +
  • +

    determinadas classes devem ter um comportamento específico (método) e outras não;

    +
  • +
  • +

    não deseja-se que uma alteração em uma super classe afete sub classes.

    +
  • +
+
+
+
+

1.3. Modelagem do Padrão

+
+
+strategy base class diagram +
+
+
+

A classe Estrategista é que que irá usar as estratégias, que são representadas pelas classes que implementam os comportamentos. +Cada comportamento (estratégia) é normalmente definido como uma interface. Assim, podem existir N implementações de cada comportamento (diferentes estratégias).

+
+
+

Perceba que a relação entre a Estrategista e os comportamentos não é herança, mas pode ser uma associação normal, composição ou agregação. Cada comportamento não é implementado como uma subclasse da Estrategista, cada tipo de comportamento estará contido como um atributo dentro da Estrategista. Por isso é comum representar como agregação/composição. Definindo o comportamento como atributo é que nos permite alterar em tempo de execução sua implementação.

+
+
+

O comportamento em si é definido por um método na interface. No exemplo, o método é executarComportamentoA() para o ComportamentoA. O nome do método é o desenvolvedor quem define, normalmente sendo um nome que faça sentido para o sistema. +A assinatura do método também é livre. Neste exemplo o método não recebe parâmetros e retorna um tipo genérico T. O tipo do retorno vai depender das suas necessidades. Veja os exemplos concretos na seção a seguir.

+
+
+

Podem existir diferentes classes filhas desta Estrategista, cada uma fazendo uso diferente do resultado de um determinado comportamento. +Com o padrão Strategy, o comportamento de qualquer classe (mãe ou filha) pode mudar em tempo de execução, de acordo com os requisitos do sistema.

+
+
+

Um projeto de exemplo para o diagrama apresentado está disponível aqui. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão.

+
+
+
+

1.4. Princípios utilizados

+
+
    +
  • +

    Favorecer composição no lugar de herança.

    +
  • +
  • +

    Programar para uma "interface" não uma implementação (GoF): declaramos variáveis com tipos abstratos (uma interface de comportamento) e usamos tipos concretos (uma classe que implementa um comportamento) apenas na instanciação.

    +
  • +
  • +

    Single Responsibility Principle (SRP) pois a classe que usa os comportamentos não tem a responsabilidade de implementar estes comportamentos. Adicionalmente, cada classe de comportamento é responsável por implementar um único comportamento. Se temos vários comportamentos, devemos ter várias classes.

    +
  • +
  • +

    Open/Closed Principle (OCP), pois separa as partes que mudam (os comportamentos) de dentro da classe que utiliza eles. Isto torna a classe "aberta para extensão e fechada para modificação" (em relação aos comportamentos).

    +
  • +
  • +

    Liskov Substitution Principle (LSP) pois podemos substituir um comportamento por qualquer implementação dele, de forma transparente, até mesmo em tempo de execução, sem que sejam necessárias alterações no código interno da classe que utiliza tais comportamentos.

    +
  • +
  • +

    Interface Segregation Principle (ISP), pois estamos definindo diferentes interfaces: uma para cada comportamento que pode ser implementado.

    +
  • +
+
+
+
+

1.5. Exemplos

+
+

+
+
+

1.5.1. Leitura de arquivos de retorno de boletos bancários.

+
+

Arquivos de retorno são enviados pelos bancos às empresas, fornecendo uma lista de boletos +pagos por clientes, para que tais empresas possam registrar o pagamento desses boletos +em seus sistemas. Os bancos utilizam um arquivo de texto com campos de comprimento fixo, onde não existe um caractere delimitador. Cada campo tem uma quantidade fixa de caracteres. Se o valor possui menos caracteres do que deveria, o tamanho é completado com espaços em branco.

+
+
+

Um aplicação na empresa recebedora dos boletos deve ler tais arquivos para extrair os dados +e normalmente gravar em um banco de dados. Existem diferentes formatos para tais arquivos +e cada banco pode utilizar um formato diferente. Atualmente existem inúmeros projetos em diferentes linguagens para fazer a leitura de tais arquivos, /retorno-boletophp[como este]. Vamos implementar um solução simplificada aqui apenas para efeitos didáticos.

+
+
+ + + + + +
+ + +Apesar de atualmente termos formatos de arquivos mais utilizados como JSON e XML, formatos como o mencionado ainda são bastante utilizados, principalmente no meio acadêmico, por serem simples. Um outro exemplo de tais formatos são os arquivos CSV. Mas em aplicações Web e mobile, o mais comum é o uso de JSON e XML. +
+
+
+

Para este exemplo, vamos considerar que o Banco do Brasil usa um tipo de arquivo onde cada linha com as informações sobre o pagamento de um boleto contém os seguintes campos, separados por ponto-e-vírgula:

+
+
+
    +
  1. +

    id do boleto com 10 dígitos

    +
  2. +
  3. +

    código do banco onde o boleto foi pago (3 dígitos)

    +
  4. +
  5. +

    data vencimento (dd/mm/yyyy)

    +
  6. +
  7. +

    data pagamento (dd/mm/yyyy)

    +
  8. +
  9. +

    CPF do cliente (sem . e -)

    +
  10. +
  11. +

    valor do boleto (decimal 10.2)

    +
  12. +
  13. +

    multa por atraso (decimal 10.2)

    +
  14. +
  15. +

    juros no formato (decimal 10.2)

    +
  16. +
+
+
+

Mas digamos que você também precisa receber arquivos do Bradesco que possui o seguinte formato:

+
+
+
    +
  1. +

    id do boleto com 10 dígitos

    +
  2. +
  3. +

    cód banco onde o boleto foi pago (3 dígitos)

    +
  4. +
  5. +

    *agência onde o boleto foi pago (6 dígitos)

    +
  6. +
  7. +

    *conta do cliente para possível estorno de pagamento (9 dígitos)

    +
  8. +
  9. +

    data vencimento (dd/mm/yyyy)

    +
  10. +
  11. +

    *data/hora pagamento (dd/mm/yyyy hh:nn:ss)

    +
  12. +
  13. +

    *CPF do cliente (com . e -)

    +
  14. +
  15. +

    valor do boleto (decimal 10.2)

    +
  16. +
  17. +

    multa por atraso (decimal 10.2)

    +
  18. +
  19. +

    juros no formato (decimal 10.2)

    +
  20. +
+
+
+

*Campos adicionais ou diferentes do formato anterior.

+
+
+

Um diagrama de classes para tal implementação pode ser como abaixo.

+
+
+

retorno boleto class diagram

+
+
+

O código fonte com uma implementação de exemplo pode ser obtido aqui (zip). +Tente primeiro fazer sua implementação a partir da leitura do diagrama, +para depois analisar o código disponibilizado.

+
+
+ + + + + +
+ + +Uma implementação em Node.js está disponível em retorno-boleto-js. +
+
+
+
+
+

1.6. Detalhes de Implementação

+
+

Mesmo que uma classe não tenha um determinado comportamento, como o definido pela interface ComportamentoA, haverá uma associação entre a classe e o comportamento. +Se a classe não precisar de uma implementação de tal comportamento, o atributo que representa a associação pode estar nulo. Ao tentar usar o comportamento é gerada a exceção NullPointerException.

+
+
+

Para resolver isso, podemos criar uma classe que tenha uma implementação vazia para o comportamento, ou seja, que não faz nada. Isto normalmente pode ser implementado pelo padrão Null Object que veremos posteriormente.

+
+
+

Se a classe estrategista é obrigada a ter um determinado comportamento, +para evitar NullPointerException, podemos não incluir um construtor sem parâmetros e incluir um que exija uma implementação de estratégia a ser usada.

+
+
+

+
+
+
+
+
+

2. Modelagem Convencional sem o padrão Strategy 🤔

+
+
+

A modelagem convencional de diferentes comportamentos sem a aplicação do padrão Strategy requer o uso de herança para os diferentes comportamentos e é visualmente mais simples. +No entanto, tal implementação tem algumas características que podem ser um problema (ou não), dependendo dos requisitos do seu sistema, por não permitir:

+
+
+
    +
  • +

    alterar um comportamento em tempo de execução;

    +
  • +
  • +

    compartilhar implementações de um mesmo comportamento entre diferentes classes filhas, levando à duplicação de código (que deve ser evitado ao máximo);

    +
  • +
  • +

    combinar comportamentos distintos em um só, reaproveitando código.

    +
  • +
+
+
+

no strategy class diagram

+
+
+
+
+

3. Como NÃO implementar uma solução para um problema 😳

+
+
+

Se o padrão não for aplicado nem a solução com herança acima, uma outra solução normalmente é implementada por meio de uma única classe. Não será mostrado nem mesmo um diagrama, pois a solução seria composta de fato apenas por uma classe. Ela então teria métodos como T executarComportamentoA(). Todas as implementações deste "Comportamento A" seriam incluídas no método citado.

+
+
+

Para o exemplo do retorno de boletos bancários, isto significa que tal método seria algo como:

+
+
+
+
public void processar(String nomeArquivo){
+    if(nomeArquivo.contains("banco-brasil")){
+        //processa arquivo do Banco do Brasil
+    }
+    else if(nomeArquivo.contains("bradesco")){
+        //processa arquivo do Bradesco
+    }
+}
+
+
+
+

Tal código é extremamente mais simples, tem uma única classe e tudo é feito em um único método. +Apesar de parecer muito melhor por simplificar as coisas e dar a impressão que estamos usando o princípio KISS, não chamaria esta solução de simples, mas simplista e ingênua. Soluções simplistas normalmente vão lhe trazer dores de cabeça para manutenção do software. +Por isto, esta "solução" é totalmente não recomendada.

+
+
+

Considerando que podemos ter diferentes formatos de arquivos para bancos distintos e que precisamos processar arquivos de vários bancos, esta solução apresenta alguns problemas. O método processar:

+
+
+
    +
  • +

    vai ficar longo e possivelmente confuso;

    +
  • +
  • +

    não tem uma única responsabilidade (viola o princípio SRP), pois ele processa arquivos de diferentes bancos, no lugar de processar arquivos de um banco específico;

    +
  • +
  • +

    cada vez que um novo banco precisar ser incluído, o código precisará ser alterado (viola o princípio OCP).

    +
  • +
+
+
+

O problema da violação do OCP é o mais problemático aqui. O uso de if’s (ou qualquer estrutura condicional como switch) para decidir qual algoritmo será executado em cada situação deixa claro que uma nova condição precisará ser adicionada sempre que um novo banco precisar ser suportado. Se em outros lugares do sistema você precisa realizar outras tarefas com estes arquivos de retorno, tende-se a repetir esta mesma cadeia de if’s. +Por exemplo, se em um lugar do sistema você precisa processar os arquivos e incluir os dados em um banco de dados e em outro você precisa processar e gerar PDFs com comprovantes de pagamentos ou enviar emails de notificação, em cada um desses locais você precisará deste bloco de if’s. +O problema surge quando você precisar incluir um novo banco e tiver que incluir um novo if em cada um desses locais. +Você pode simplesmente esquecer de adicionar tal if em todos os locais necessários e o recurso funcionar em parte do sistema e em outras partes não.

+
+
+

+
+
+
+
+

4. Modelagem do Padrão utilizando Programação Funcional

+
+ +
+

Observando o diagrama base para a implementação do padrão Strategy, pode-se perceber que são criadas muitas classes e interfaces. As classes implementando essas interfaces não possuem atributos e têm apenas um único método que representa a implementação da estratégia em si.

+
+
+

Graças à Programação Funcional em diversas linguagens como Java 8+, JavaScript, Phython e outras, podemos simplificar este diagrama, e consequentemente a implementação, como mostra a figura a seguir.

+
+
+

strategy base funcional class diagram

+
+
+

Observe que não temos mais as interfaces e classes específicas dos comportamentos. Cada comportamento nada mais é do que a implementação de um método (como o executarComportamentoA() do primeiro diagrama). O que precisamos de fato é permitir a troca da implementação de tal método em tempo de execução. Mas para isso, usando Programação Orientada a Objetos, tivemos que primeiro criar um conjunto de classes e interfaces pra isso.

+
+
+

Usando Programação Funcional podemos armazenar uma função em uma variável, no lugar de ter que armazenar um objeto inteiro que possui apenas um único método. A partir de tal variável, podemos então chamar a função. Se uma nova função for atribuída a tal variável, quando usarmos a variável novamente, estaremos chamando esta nova função, como espera-se que o padrão Strategy funcione.

+
+
+

No diagrama, o atributo como comportamentoA é do tipo Function, uma interface do Java 8+ (dentro muitas outras) que indica que o atributo contém uma referência para um método que a classe pode chamar, no lugar de armazenar um dado primitivo ou objeto convencional. Sendo que a referência para o método está armazenada em um atributo, se tivermos um método como o comportamentoA1 mostrado no primeiro diagrama, podemos armazenar uma referência para tal método no atributo comportamentoA. +Se precisarmos fazer a super classe ou qualquer subclasse usar um comportamento diferente, podemos atribuir, por exemplo, o método comportamentoA2 ao atributo comportamentoA em tempo de execução.

+
+
+

Function é uma das interfaces em Java 8+ que permite representar métodos isolados e armazenar referências deles em variáveis. +Estas são chamadas de interfaces funcionais. Lembre-se que interfaces são como tipos. Assim como uma variável do tipo int indica que somente números inteiros podem ser armazenados nela, uma interface funcional indica o tipo de métodos que podem ser atribuídos a uma variável de tal tipo. +Em outras palavras, tais interfaces indicam que assinatura um método deve ter para ser possível atribuí-lo a uma variável cujo tipo é uma interface funcional.

+
+
+

Uma variável Function indica que podemos atribuir a ela qualquer método que receba um único parâmetro e retorne um determinado valor. +Se voltarmos ao exemplo dos boletos, a assinatura do nosso método que implementa os comportamentos de leitura dos arquivos de retorno é:

+
+
+
+
List<Boleto> lerArquivo(String nomeArquivo)
+
+
+
+

Observe que tal função/método recebe um parâmetro (neste caso String) e retorna um valor (List<Boleto>). +Assim, uma função como lerArquivo pode então ser atribuída a uma variável do tipo Function. +Se você tiver um método com uma assinatura diferente e precisar armazenar tal método em um variável, +justamente para permitir trocar a implementação de tal método em tempo de execução usando Programação Funcional, +um ponto de partida é estudar a documentação do pacote java.util.function que descreve as interfaces funcionais padrões do Java 8+.

+
+
+

Programação funcional é um assunto bastante extenso que poderia ser um curso totalmente a parte, +que envolve muitos conceitos novos. Existe muito material disponível na internet. +Mas é difícil encontrar material gratuito, em português e abrangentes. +Existe muito material em inglês, mas novamente espalhado pela web. +Se desejarem aprofundar no assunto, acessem esta página.

+
+
+

O código fonte do projeto usando programação funcional está disponível aqui (zip).

+
+
+ + + + + +
+ + +Em linguagens distintas, a forma de implementar o padrão Strategy usando programação funcional é diferente. +
+
+
+
+
+

5. Padrões Relacionados

+
+
+

Padrões que possuem similaridades ou podem ser usados em conjunto:

+
+
+ +
+
+
+
+

6. Onde o padrão é usado no JDK

+
+
+

Um forma de identificar a aplicação do padrão Strategy nas classes do JDK que você usa é quando um método requer uma interface que possui apenas um método a ser implementado. Estas são chamadas de interfaces funcionais a partir do Java 8 (que possivelmente estão anotadas com @FunctionalInterface). A implementação de tal interface não é fornecida pelo JDK mas por você. +Você deve então fornecer um algoritmo (função) que será executado pela classe que estiver utilizando o padrão.

+
+
+

6.1. List.sort(Comparator<T> comparator)

+
+

Tal método da interface List permite ordenar os valores dentra da lista. +Comparator é uma interface cujas implementações representam as estratégias de ordenação de uma lista. Comparator é uma interface funcional, logo, conseguimos usar programação funcional para implementar as estratégias apenas criando-se funções. Assim, não temos que obrigatoriamente criar uma classe para cada estratégia. Como podemos implementar ordenação de uma infinidade de maneiras como:

+
+
+
    +
  • +

    por ordem alfabética crescente ou descrescente;

    +
  • +
  • +

    utilizando algoritmos mais ou menos eficientes como Bubble Sort, Shell Sort, Quick Sort, etc

    +
  • +
+
+
+

usar o padrão Strategy aqui faz todo o sentido. Podemos inclusive em um momento ordenar +uma lista de uma maneira e posteriormente decidirmos que queremos ordenar de outra maneira.

+
+
+
+
+
+

7. Exercícios

+
+
+

7.1. Descontos

+
+

Considere que temos um sistema de vendas onde diferentes formas de desconto podem ser implementadas de acordo as promoções vigentes, como em datas comemorativas. O sistema deve permitir o cálculo do desconto sobre a venda das seguintes maneiras:

+
+
+
    +
  • +

    percentual de desconto definido (que pode vir de um banco de dados);

    +
  • +
  • +

    percentual de desconto progressivo: valor da compra/25, não podendo ultrapassar 20%;

    +
  • +
  • +

    desconto de 15% na data de aniversário do cliente;

    +
  • +
+
+
+

E como poderíamos implementar estes tipos de desconto sem utilizar Padrões de Projetos? +Quais os problemas que tal implementação traria?

+
+
+
+

7.2. Ordenação de Listas

+
+

Ordenar uma lista de estudantes utilizando programação funcional no Java 8+. +O projeto disponível aqui (zip) pode ser usado como base, pois ele gera uma lista de estudantes aleatoriamente.

+
+
+
+

7.3. Diferenças da implementação puramente OO vs funcional

+
+

A página inicial do projeto funcional disponível aqui (zip) apresenta algumas diferenças +de implementação do padrão Strategy utilizando puramente programação orientada a objetos e outra versão +utilizando programação funcional.

+
+
+

Descreva em detalhes qual a diferença em utilizar um atributo do tipo LeituraRetorno na implementação puramente OO +e um atributo do tipo Function na implementação funcional.

+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/01-strategy/index.html b/comportamentais/01-strategy/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/01-strategy/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/01-strategy/modelagem/README.adoc b/comportamentais/01-strategy/modelagem/README.adoc deleted file mode 100755 index e0cb4252c..000000000 --- a/comportamentais/01-strategy/modelagem/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ -= Modelagem do Padrão Strategy (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/01-strategy/modelagem/[zip]) - -Apresenta um código de exemplo da modelagem do padrão Strategy. -Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. -Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos. diff --git a/comportamentais/01-strategy/modelagem/README.html b/comportamentais/01-strategy/modelagem/README.html new file mode 100644 index 000000000..eab81d742 --- /dev/null +++ b/comportamentais/01-strategy/modelagem/README.html @@ -0,0 +1,454 @@ + + + + + + + +Modelagem do Padrão Strategy (zip) + + + + + +
+
+

Apresenta um código de exemplo da modelagem do padrão Strategy. +Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. +Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos.

+
+
+ + + \ No newline at end of file diff --git a/comportamentais/01-strategy/modelagem/index.html b/comportamentais/01-strategy/modelagem/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/01-strategy/modelagem/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/01-strategy/ordenar-lista-base/README.adoc b/comportamentais/01-strategy/ordenar-lista-base/README.adoc deleted file mode 100755 index 379f37df7..000000000 --- a/comportamentais/01-strategy/ordenar-lista-base/README.adoc +++ /dev/null @@ -1,8 +0,0 @@ -= Aplicação de exemplo para ordenação de uma lista de estudantes (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/01-strategy/ordenar-lista-base[zip]) - -Este é um projeto Java 11 base que gera uma lista aleatório de estudantes -para que você possa implementar seu próprio código. - -Implemente seu próprio código utilizando os recursos de programação funcional introduzidos no JDK 8, -por meio do método `sort()` da interface `List` para ordenar -tal lista de estudantes. Inclua seu código na classe `AppProgramacaoFuncional`. diff --git a/comportamentais/01-strategy/ordenar-lista-base/README.html b/comportamentais/01-strategy/ordenar-lista-base/README.html new file mode 100644 index 000000000..80c35d0f4 --- /dev/null +++ b/comportamentais/01-strategy/ordenar-lista-base/README.html @@ -0,0 +1,458 @@ + + + + + + + +Aplicação de exemplo para ordenação de uma lista de estudantes (zip) + + + + + +
+
+

Este é um projeto Java 11 base que gera uma lista aleatório de estudantes +para que você possa implementar seu próprio código.

+
+
+

Implemente seu próprio código utilizando os recursos de programação funcional introduzidos no JDK 8, +por meio do método sort() da interface List para ordenar +tal lista de estudantes. Inclua seu código na classe AppProgramacaoFuncional.

+
+
+ + + \ No newline at end of file diff --git a/comportamentais/01-strategy/ordenar-lista-base/index.html b/comportamentais/01-strategy/ordenar-lista-base/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/01-strategy/ordenar-lista-base/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/01-strategy/ordenar-lista/README.adoc b/comportamentais/01-strategy/ordenar-lista/README.adoc deleted file mode 100755 index 10455d122..000000000 --- a/comportamentais/01-strategy/ordenar-lista/README.adoc +++ /dev/null @@ -1,8 +0,0 @@ -= Aplicação de exemplo para ordenação de uma lista de estudantes (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/01-strategy/ordenar-lista[zip]) - -Este é um projeto Java 11 que gera uma lista aleatório de estudantes. -O projeto utiliza recursos de programação funcional introduzidos no JDK 8, -por meio do método `sort()` da interface `List` para ordenar -tal lista de estudantes. - -O código é implementado na classe `AppProgramacaoFuncional`. diff --git a/comportamentais/01-strategy/ordenar-lista/README.html b/comportamentais/01-strategy/ordenar-lista/README.html new file mode 100644 index 000000000..49be51e59 --- /dev/null +++ b/comportamentais/01-strategy/ordenar-lista/README.html @@ -0,0 +1,458 @@ + + + + + + + +Aplicação de exemplo para ordenação de uma lista de estudantes (zip) + + + + + +
+
+

Este é um projeto Java 11 que gera uma lista aleatório de estudantes. +O projeto utiliza recursos de programação funcional introduzidos no JDK 8, +por meio do método sort() da interface List para ordenar +tal lista de estudantes.

+
+
+

O código é implementado na classe AppProgramacaoFuncional.

+
+
+ + + \ No newline at end of file diff --git a/comportamentais/01-strategy/ordenar-lista/index.html b/comportamentais/01-strategy/ordenar-lista/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/01-strategy/ordenar-lista/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/01-strategy/retorno-boleto-funcional/README.adoc b/comportamentais/01-strategy/retorno-boleto-funcional/README.adoc deleted file mode 100644 index 750903868..000000000 --- a/comportamentais/01-strategy/retorno-boleto-funcional/README.adoc +++ /dev/null @@ -1,73 +0,0 @@ -:imagesdir: ../../../images/patterns/strategy -:source-highlighter: highlightjs -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Leitura de Retorno de Boletos Bancários usando Strategy Pattern com Programação Funcional (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/01-strategy/retorno-boleto-funcional[zip]) - -IMPORTANT: https://youtu.be/hsRbUGTV2ok[Víde-aula sobre os detalhes da implementação funcional deste projeto]. - -Esta versão do projeto implementa a leitura de retorno de boletos de uma forma mais -simples utilizando programação funcional no Java 8+. -Com tais recursos, precisamos criar menos classes para fornecer uma implementação -do padrão Strategy. - -A implementação é baseada no diagrama a seguir: - -image:strategy-base-funcional-class-diagram.png[] - -== Detalhes de Implementação - -Ao criar uma implementação funcional para o padrão Strategy, além de reduzir o número -de classes que temos que criar, depois de entender os conceitos de programação funcional, -perceba que a essência de como implementar o padrão não muda. - -Usando a implementação puramente orientada a objetos, a classe `ProcessarBoletos` -possui um código como: - -[source,java] ----- -public class ProcessarBoletos { - private LeituraRetorno leituraRetorno; - - public final void processar(String nomeArquivo){ - List boletos = leituraRetorno.lerArquivo(nomeArquivo); - for (Boleto boleto : boletos) { - System.out.println(boleto); - } - } -} ----- - -Já a mesma classe no projeto funcional possui a seguinte implementação de tal classe: - -[source,java] ----- -public class ProcessarBoletos { - private Function> leituraRetorno; - - public void processar(String nomeArquivo){ - List boletos = leituraRetorno.apply(nomeArquivo); - for (Boleto boleto : boletos) { - System.out.println(boleto); - } - } -} ----- - -Observe que o código é praticamente o mesmo, só muda que na primeira implementação -temos um atributo `leituraRetorno` do tipo `LeituraRetorno`, esta uma interface que possui um método `lerArquivo()`. -Já na implementação funcional, a estratégia é definida por meio de um -atributo de mesmo nome, mas do tipo `Function`, que armazena a implementação (a função) -a ser utilizada para ler de fato o arquivo. `Function` é o que chamamos de interface funcional a partir do Java 8. -Como ela não foi definida por nós, ela já possui um método definido, chamado `apply`. -Assim, internamente, o método `processar` da classe estrategista (`ProcessarBoletos`) apenas -chama um método diferente na primeira linha dos métodos `processar` nos exemplos acima. diff --git a/comportamentais/01-strategy/retorno-boleto-funcional/README.html b/comportamentais/01-strategy/retorno-boleto-funcional/README.html new file mode 100644 index 000000000..cc0ee1e66 --- /dev/null +++ b/comportamentais/01-strategy/retorno-boleto-funcional/README.html @@ -0,0 +1,541 @@ + + + + + + + +Leitura de Retorno de Boletos Bancários usando Strategy Pattern com Programação Funcional (zip) + + + + + + + +
+
+
+ +
+

Esta versão do projeto implementa a leitura de retorno de boletos de uma forma mais +simples utilizando programação funcional no Java 8+. +Com tais recursos, precisamos criar menos classes para fornecer uma implementação +do padrão Strategy.

+
+
+

A implementação é baseada no diagrama a seguir:

+
+
+

strategy base funcional class diagram

+
+
+
+
+

Detalhes de Implementação

+
+
+

Ao criar uma implementação funcional para o padrão Strategy, além de reduzir o número +de classes que temos que criar, depois de entender os conceitos de programação funcional, +perceba que a essência de como implementar o padrão não muda.

+
+
+

Usando a implementação puramente orientada a objetos, a classe ProcessarBoletos +possui um código como:

+
+
+
+
public class ProcessarBoletos {
+    private LeituraRetorno leituraRetorno;
+
+    public final void processar(String nomeArquivo){
+        List<Boleto> boletos = leituraRetorno.lerArquivo(nomeArquivo);
+        for (Boleto boleto : boletos) {
+            System.out.println(boleto);
+        }
+    }
+}
+
+
+
+

Já a mesma classe no projeto funcional possui a seguinte implementação de tal classe:

+
+
+
+
public class ProcessarBoletos {
+    private Function<String, List<Boleto>> leituraRetorno;
+
+    public void processar(String nomeArquivo){
+        List<Boleto> boletos = leituraRetorno.apply(nomeArquivo);
+        for (Boleto boleto : boletos) {
+            System.out.println(boleto);
+        }
+    }
+}
+
+
+
+

Observe que o código é praticamente o mesmo, só muda que na primeira implementação +temos um atributo leituraRetorno do tipo LeituraRetorno, esta uma interface que possui um método lerArquivo(). +Já na implementação funcional, a estratégia é definida por meio de um +atributo de mesmo nome, mas do tipo Function, que armazena a implementação (a função) +a ser utilizada para ler de fato o arquivo. Function é o que chamamos de interface funcional a partir do Java 8. +Como ela não foi definida por nós, ela já possui um método definido, chamado apply. +Assim, internamente, o método processar da classe estrategista (ProcessarBoletos) apenas +chama um método diferente na primeira linha dos métodos processar nos exemplos acima.

+
+
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/01-strategy/retorno-boleto-funcional/index.html b/comportamentais/01-strategy/retorno-boleto-funcional/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/01-strategy/retorno-boleto-funcional/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/01-strategy/retorno-boleto-reflection/README.adoc b/comportamentais/01-strategy/retorno-boleto-reflection/README.adoc deleted file mode 100755 index bcc9959e7..000000000 --- a/comportamentais/01-strategy/retorno-boleto-reflection/README.adoc +++ /dev/null @@ -1,36 +0,0 @@ -:source-highlighter: highlightjs - -= Leitura de Retorno de Boletos Bancários usando Strategy Pattern e Java Reflection (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/01-strategy/retorno-boleto-reflection[zip]) - -Esta é uma versão diferente do projeto de leitura de arquivos de retorno de boletos bancários. Tal versão requer no mínimo o Java 9 para compilar e executar. O projeto está configurado para usar Java 11, mas pode-se alterar para qualquer versão a partir da 9. Ele aplica o recurso de https://www.devmedia.com.br/conhecendo-java-reflection/29148[Reflection do Java] para permitir usar um laço de repetição `for` para atribuir o valor de cada campo lido de um arquivo de retorno para o atributo correspondente em um objeto `Boleto`. - -Tal versão usa recursos de métodos `default` (com implementação) do Java 8 e métodos privados do Java 9 em Interfaces. Além disso, o projeto usa recursos de programação funcional. - -Usando este projeto, no lugar de escrever uma linha de código para cada campo que desejarmos pegar do arquivo e armazenar em um objeto `Boleto`, como abaixo: - -[source,java] ----- -boleto.setId(Integer.parseInt(vetor[0])); -boleto.setCodBanco(vetor[1]); -boleto.setDataVencimento(LocalDate.parse(vetor[2], FORMATO_DATA)); ----- - -podemos usar um `for` semelhante ao seguinte: - -```java -for (int i = 0; i < totalCampos; i++) { - setCampoBoleto(i, boleto, vetor[i]); -} -``` - -== AVISO - -Apesar desta facilitade, o código é muito mais complicado e confuso para quem não entende de __Reflection__. -O código do projeto anterior é claro e direto. -A versão aqui apresentada serve apenas como curiosidade. Em uma aplicação real, esta implementação não é nada aconselhável, pois é mais complexa e a execução usando __Reflection__ é mais lenta. -__Reflection__ é bastante usado em Java, mas quando não há uma maneira mais simples de resolver um problema. - -Em linguagens dinâmicas como JavaScript, conseguiríamos usar um `for` para esta tarefa naturalmente, sem precisar recorrer a recursos avançados da linguagem e nem tornar o código mais complexo. - -Então, o projeto serve apenas para mostrar alguns recursos avançados da linguagem Java, -sendo um ótimo material de estudos. diff --git a/comportamentais/01-strategy/retorno-boleto-reflection/README.html b/comportamentais/01-strategy/retorno-boleto-reflection/README.html new file mode 100644 index 000000000..d7108bd3b --- /dev/null +++ b/comportamentais/01-strategy/retorno-boleto-reflection/README.html @@ -0,0 +1,505 @@ + + + + + + + +Leitura de Retorno de Boletos Bancários usando Strategy Pattern e Java Reflection (zip) + + + + + + +
+
+
+
+

Esta é uma versão diferente do projeto de leitura de arquivos de retorno de boletos bancários. Tal versão requer no mínimo o Java 9 para compilar e executar. O projeto está configurado para usar Java 11, mas pode-se alterar para qualquer versão a partir da 9. Ele aplica o recurso de Reflection do Java para permitir usar um laço de repetição for para atribuir o valor de cada campo lido de um arquivo de retorno para o atributo correspondente em um objeto Boleto.

+
+
+

Tal versão usa recursos de métodos default (com implementação) do Java 8 e métodos privados do Java 9 em Interfaces. Além disso, o projeto usa recursos de programação funcional.

+
+
+

Usando este projeto, no lugar de escrever uma linha de código para cada campo que desejarmos pegar do arquivo e armazenar em um objeto Boleto, como abaixo:

+
+
+
+
boleto.setId(Integer.parseInt(vetor[0]));
+boleto.setCodBanco(vetor[1]);
+boleto.setDataVencimento(LocalDate.parse(vetor[2], FORMATO_DATA));
+
+
+
+

podemos usar um for semelhante ao seguinte:

+
+
+
+
for (int i = 0; i < totalCampos; i++) {
+    setCampoBoleto(i, boleto, vetor[i]);
+}
+
+
+
+
+
+

AVISO

+
+
+

Apesar desta facilitade, o código é muito mais complicado e confuso para quem não entende de Reflection. +O código do projeto anterior é claro e direto. +A versão aqui apresentada serve apenas como curiosidade. Em uma aplicação real, esta implementação não é nada aconselhável, pois é mais complexa e a execução usando Reflection é mais lenta. +Reflection é bastante usado em Java, mas quando não há uma maneira mais simples de resolver um problema.

+
+
+

Em linguagens dinâmicas como JavaScript, conseguiríamos usar um for para esta tarefa naturalmente, sem precisar recorrer a recursos avançados da linguagem e nem tornar o código mais complexo.

+
+
+

Então, o projeto serve apenas para mostrar alguns recursos avançados da linguagem Java, +sendo um ótimo material de estudos.

+
+
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/01-strategy/retorno-boleto-reflection/index.html b/comportamentais/01-strategy/retorno-boleto-reflection/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/01-strategy/retorno-boleto-reflection/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/01-strategy/retorno-boleto/README.adoc b/comportamentais/01-strategy/retorno-boleto/README.adoc deleted file mode 100755 index 16ec14b6e..000000000 --- a/comportamentais/01-strategy/retorno-boleto/README.adoc +++ /dev/null @@ -1,21 +0,0 @@ -:imagesdir: ../../../images/patterns/strategy -:source-highlighter: highlightjs -:numbered: -:unsafe: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Leitura de arquivos de retorno de boletos bancários utilizando Padrão Strategy (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/01-strategy/retorno-boleto[zip]) - -Esta é a implementação da leitura de arquivos de retorno de boletos bancários, como explicado na link:../[pasta anterior], -utilizando o padrão Strategy. Veja a modelagem a seguir. - -image:retorno-boleto-class-diagram.png[] - diff --git a/comportamentais/01-strategy/retorno-boleto/README.html b/comportamentais/01-strategy/retorno-boleto/README.html new file mode 100644 index 000000000..39de550cf --- /dev/null +++ b/comportamentais/01-strategy/retorno-boleto/README.html @@ -0,0 +1,464 @@ + + + + + + + +Leitura de arquivos de retorno de boletos bancários utilizando Padrão Strategy (zip) + + + + + + +
+
+

Esta é a implementação da leitura de arquivos de retorno de boletos bancários, como explicado na pasta anterior, +utilizando o padrão Strategy. Veja a modelagem a seguir.

+
+
+

retorno boleto class diagram

+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/01-strategy/retorno-boleto/index.html b/comportamentais/01-strategy/retorno-boleto/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/01-strategy/retorno-boleto/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/01-strategy/slides-strategy-funcional.adoc b/comportamentais/01-strategy/slides-strategy-funcional.adoc deleted file mode 100644 index b8bbcbc8b..000000000 --- a/comportamentais/01-strategy/slides-strategy-funcional.adoc +++ /dev/null @@ -1,39 +0,0 @@ -//:revealjsdir: https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.8.0/ -:revealjsdir: https://unpkg.com/reveal.js@4.3.1 -:revealjs_slideNumber: true -:source-highlighter: highlightjs -:icons: font -:allow-uri-read: -:stylesheet: ../../adoc-golo.css -:customcss: ../../slides-base.css -:numbered: -:toc: left -:toc-title: Sumário -:toclevels: 5 - -ifdef::env-github[] -//Exibe ícones para os blocos como NOTE e IMPORTANT no GitHub - -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -:chapter-label: -:listing-caption: Listagem -:figure-caption: Figura - -//Transição para todos os slides // none/fade/slide/convex/concave/zoom -//:revealjs_transition: 'zoom' - -//https://github.com/hakimel/reveal.js#theming -:revealjs_theme: league - -// = Padrão Strategy com Programação Funcional no Java 8 image:images/strategy-icon.png[width=16%] - -= Strategy Funcional: https://docs.google.com/presentation/d/e/2PACX-1vRzqcUXSv7IRqhFo0zPmeS8OY17NG4LplA6ZNRQ6lTI02IYteX5t2EJTsmP_24xsYPBONE6WvarLWYH/pub?start=false&loop=false&delayms=3000[Link pro Google Slides (converter para adoc posteriormente)] - - - diff --git a/comportamentais/01-strategy/slides-strategy-funcional.html b/comportamentais/01-strategy/slides-strategy-funcional.html new file mode 100644 index 000000000..b591dbc3f --- /dev/null +++ b/comportamentais/01-strategy/slides-strategy-funcional.html @@ -0,0 +1,680 @@ + + + + + + + +Strategy Funcional: Link pro Google Slides (converter para adoc posteriormente) + + + + + + +
+ +
+ + + + + \ No newline at end of file diff --git a/comportamentais/01-strategy/slides.adoc b/comportamentais/01-strategy/slides.adoc deleted file mode 100644 index 8448b28b0..000000000 --- a/comportamentais/01-strategy/slides.adoc +++ /dev/null @@ -1,177 +0,0 @@ -:revealjsdir: https://unpkg.com/reveal.js@4.3.1 -:revealjs_slideNumber: true -:source-highlighter: highlightjs -:icons: font -:allow-uri-read: -:stylesheet: ../../adoc-golo.css -:customcss: ../../slides-base.css -:numbered: -:toc: left -:toc-title: Sumário -:toclevels: 5 - -ifdef::env-github[] -//Exibe ícones para os blocos como NOTE e IMPORTANT no GitHub - -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -:chapter-label: -:listing-caption: Listagem -:figure-caption: Figura - -//Transição para todos os slides // none/fade/slide/convex/concave/zoom -//:revealjs_transition: 'zoom' - -//https://github.com/hakimel/reveal.js#theming -:revealjs_theme: league - -= Padrão de Projetos Strategy image:images/strategy-icon.png[width=16%] - -Prof. Manoel Campos - -image::https://manoelcampos.com/padroes-projetos/images/biolink.png[] - -[transition=zoom] -== Categoria - -Padrão de projeto Comportamental image:../../images/behaviour.gif[] - -[transition=fade] -== Definição - -include::README.adoc[tag=definicao] - -image:../../images/ucpp.jpg[size=contain] - -[transition=zoofadem] -== Aplicabilidade - -[%step] -include::README.adoc[tag=aplicabilidade] - -[transition=zoom] -== Modelagem do Strategy - -image::images/diagram.png[background, size=contain] - -== ! - -image::../../images/patterns/strategy/strategy-base-class-diagram.png[background, size=contain] - -[transition=zoom, background-opacity=0.4] -== Princípios utilizados - -image::../../images/recommendations.jpg[background, size=contain, text=https://www.smart-energy.com, link=https://www.smart-energy.com/industry-sectors/smart-energy/five-key-recommendations-for-the-sustainable-energy-sector-growth-in-mena/] - -== Princípios utilizados - -[%step] -- Favorecer composição no lugar de herança -- Baixo acoplamento -- Programar para uma "interface" não uma implementação (GoF) - -== ! - -image::images/solid-ugonna-thelma.png[background] - - -== ! - -image::images/solid-ugonna-thelma.png[width=40%] - -[%step] -- **S**_ingle Responsitiliby Principle_ (SRP) -- **O**_pen/Closed Principle_ (OCP) -- **L**_iskov Substitution Principle_ (LSP) -- **I**_nterface Segregation Principle_ (ISP) -- **D**_ependency Inversion Principle_ (DIP) - -== Princípios SOLID utilizados - -[%step] -- Single Responsibility Principle (SRP) -- Open/Closed Principle (OCP) -- Liskov Substitution Principle (LSP) -- Interface Segregation Principle (ISP) - -[transition=zoom] -== ! - -- Exemplo: Leitura de arquivos de retorno de boletos bancários. - -image::images/boleto-iugu-lp.png[background] - -== ! - -include::README.adoc[tag=campos-boleto1] - -== ! - -[start=3] -include::README.adoc[tag=campos-boleto2] - -[transition=zoom] -== ! - -Aplicação do Strategy pro Retorno Boleto - -image::images/strategy-icon.png[width=16%] - -image::images/boleto-iugu-lp.png[background] - -== Modelagem Conceitual do Strategy - -image:../../images/patterns/strategy/strategy-base-class-diagram.png[size=contain] - -[transition=zoom] -== Diagrama Retorno Boleto 💵 Strategy - -== ! - -image::../../images/patterns/strategy/retorno-boleto-class-diagram.png[background, size=contain] - -[transition=zoom] -== ! - -Modelagem Convencional sem o padrão Strategy 🤔 - -image::../../images/patterns/strategy/no-strategy-class-diagram.png[background, size=contain] - -[transition=zoom] -== Modelagem sem o padrão não permite - -image::../../images/patterns/strategy/no-strategy-class-diagram.png[width=50%] - -[%step] -- alterar um comportamento em tempo de execução; -- compartilhar implementações entre classes filhas; -- combinar comportamentos em um só. - -[transition=zoom] -== Como **NÃO** implementar uma solução 😳 - -include::README.adoc[tag=como-nao-implementar] - -[transition=zoom] -== ! - -Modelagem anterior sem o padrão: utilizando herança - -image::../../images/patterns/strategy/no-strategy-class-diagram.png[background, size=contain] - -[transition=fade] -== ! - -Referências - -- “Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos”. 2006 [GoF]. -- “Use a Cabeça! Padrões de Projetos”, 2008 [UCPP]. -- “Agile software development principles, patterns, and practices”, Robert Martin, 2011. [ASDPPP] -- https://medium.com/@brunobandev/os-princ%C3%ADpios-s-o-l-i-d-em-imagens-1b5233479c21[Os princípios S.O.L.I.D em imagens] -- https://doi.org/10.1145/197320.197383[Liskov, B H. A behavioral notion of subtyping (1994).] -- https://books.google.com.br/books?id=GXWkDwAAQBAJ&printsec=frontcover[Código Limpo: Habilidades Práticas do Agile Software], Robert Martin, 2019. diff --git a/comportamentais/01-strategy/slides.html b/comportamentais/01-strategy/slides.html new file mode 100644 index 000000000..58fb262c0 --- /dev/null +++ b/comportamentais/01-strategy/slides.html @@ -0,0 +1,1084 @@ + + + + + + + +Padrão de Projetos Strategy + + + + + + +
+
+
+
+

Prof. Manoel Campos

+
+
+
+biolink +
+
+
+
+
+

1. Categoria

+
+
+

Padrão de projeto Comportamental behaviour

+
+
+
+
+

2. Definição

+
+
+

📘"O padrão Strategy define uma família de algoritmos, encapsula cada um deles e os torna intercambiáveis. A estratégia deixa o algoritmo variar independentemente dos clientes que o utilizam" [UCPP].

+
+
+

ucpp

+
+
+
+
+

3. Aplicabilidade

+
+
+
    +
  • +

    o comportamento de um método (implementação de um algoritmo) precisa ser diferente em classes distintas e/ou mudar em tempo de execução;

    +
  • +
  • +

    determinadas classes devem ter um comportamento específico (método) e outras não;

    +
  • +
  • +

    não deseja-se que uma alteração em uma super classe afete sub classes.

    +
  • +
+
+
+
+
+

4. Modelagem do Strategy

+
+
+
+background +
+
+
+
+
+

5. !

+
+
+
+background +
+
+
+
+
+

6. Princípios utilizados

+
+
+
+background +
+
+
+
+
+

7. Princípios utilizados

+
+
+
    +
  • +

    Favorecer composição no lugar de herança

    +
  • +
  • +

    Baixo acoplamento

    +
  • +
  • +

    Programar para uma "interface" não uma implementação (GoF)

    +
  • +
+
+
+
+
+

8. !

+
+
+
+background +
+
+
+
+
+

9. !

+
+
+
+solid ugonna thelma +
+
+
+
    +
  • +

    Single Responsitiliby Principle (SRP)

    +
  • +
  • +

    Open/Closed Principle (OCP)

    +
  • +
  • +

    Liskov Substitution Principle (LSP)

    +
  • +
  • +

    Interface Segregation Principle (ISP)

    +
  • +
  • +

    Dependency Inversion Principle (DIP)

    +
  • +
+
+
+
+
+

10. Princípios SOLID utilizados

+
+
+
    +
  • +

    Single Responsibility Principle (SRP)

    +
  • +
  • +

    Open/Closed Principle (OCP)

    +
  • +
  • +

    Liskov Substitution Principle (LSP)

    +
  • +
  • +

    Interface Segregation Principle (ISP)

    +
  • +
+
+
+
+
+

11. !

+
+
+
    +
  • +

    Exemplo: Leitura de arquivos de retorno de boletos bancários.

    +
  • +
+
+
+
+background +
+
+
+
+
+

12. !

+
+
+
    +
  1. +

    id do boleto com 10 dígitos

    +
  2. +
  3. +

    código do banco onde o boleto foi pago (3 dígitos)

    +
  4. +
  5. +

    data vencimento (dd/mm/yyyy)

    +
  6. +
  7. +

    data pagamento (dd/mm/yyyy)

    +
  8. +
  9. +

    CPF do cliente (sem . e -)

    +
  10. +
  11. +

    valor do boleto (decimal 10.2)

    +
  12. +
  13. +

    multa por atraso (decimal 10.2)

    +
  14. +
  15. +

    juros no formato (decimal 10.2)

    +
  16. +
+
+
+
+
+

13. !

+
+
+
    +
  1. +

    *agência onde o boleto foi pago (6 dígitos)

    +
  2. +
  3. +

    *conta do cliente para possível estorno de pagamento (9 dígitos)

    +
  4. +
  5. +

    data vencimento (dd/mm/yyyy)

    +
  6. +
  7. +

    *data/hora pagamento (dd/mm/yyyy hh:nn:ss)

    +
  8. +
  9. +

    *CPF do cliente (com . e -)

    +
  10. +
  11. +

    valor do boleto (decimal 10.2)

    +
  12. +
  13. +

    multa por atraso (decimal 10.2)

    +
  14. +
  15. +

    juros no formato (decimal 10.2)

    +
  16. +
+
+
+
+
+

14. !

+
+
+

Aplicação do Strategy pro Retorno Boleto

+
+
+
+strategy icon +
+
+
+
+background +
+
+
+
+
+

15. Modelagem Conceitual do Strategy

+
+
+

strategy base class diagram

+
+
+
+
+

16. Diagrama Retorno Boleto 💵 Strategy

+
+ +
+
+
+

17. !

+
+
+
+background +
+
+
+
+
+

18. !

+
+
+

Modelagem Convencional sem o padrão Strategy 🤔

+
+
+
+background +
+
+
+
+
+

19. Modelagem sem o padrão não permite

+
+
+
+no strategy class diagram +
+
+
+
    +
  • +

    alterar um comportamento em tempo de execução;

    +
  • +
  • +

    compartilhar implementações entre classes filhas;

    +
  • +
  • +

    combinar comportamentos em um só.

    +
  • +
+
+
+
+
+

20. Como NÃO implementar uma solução 😳

+
+
+
+
public void processar(String nomeArquivo){
+    if(nomeArquivo.contains("banco-brasil")){
+        //processa arquivo do Banco do Brasil
+    }
+    else if(nomeArquivo.contains("bradesco")){
+        //processa arquivo do Bradesco
+    }
+}
+
+
+
+
+
+

21. !

+
+
+

Modelagem anterior sem o padrão: utilizando herança

+
+
+
+background +
+
+
+
+
+

22. !

+
+
+

Referências

+
+
+ +
+
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/02-template-method/README.adoc b/comportamentais/02-template-method/README.adoc deleted file mode 100755 index 4b4a2f288..000000000 --- a/comportamentais/02-template-method/README.adoc +++ /dev/null @@ -1,231 +0,0 @@ -:imagesdir: images/ -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Comportamentais - -== Template Method (Método Modelo) image:template.png[link=https://www.flaticon.com/authors/monkik] - -NOTE: https://youtu.be/rg8_0f6bWWo[Vídeo de apresentação do padrão.] - -=== Definição - -// tag::definicao[] -📘"Especifica o esqueleto de um algoritmo dentro de um método, transferindo alguns de seus passos pras subclasses. Permite que as subclasses alterem certos passos do algoritmo sem alterar a estrutura dele." <> -// end::definicao[] - -=== Aplicabilidade - -Pode ser aplicado quando: - -// tag::aplicabilidade[] -- um método (algoritmo) possuir determinados passos definidos mas outros não; a implementação destes outros passos variar de uma subclasse para outra. -- você começar a implementar um método em diversas subclasses e verificar que existem partes comuns (código duplicado) e outras partes que mudam de uma subclasse para outra. -// end::aplicabilidade[] - -=== Modelagem do Padrão - -image:template-method-base.png[] - -A classe que implementará o Template Method realmente deve ser uma classe abstrata ou uma interface do Java 8+ com um método `default` (que possui implementação). No diagrama, o `templateMethod()` é que implementa o padrão. Ele que define a estrutudo do algoritmo a ser implementado. -Os métodos como `operacaoPrimitivaN()` são então métodos abstratos, que definem parte da implementação do algoritmo do `templateMethod()`. -Tais operações primitivas são então chamadas em algum lugar dentro do `templateMethod()`. -Cada subclasse pode ter sua própria implementação de cada uma destas operações. - -Um projeto de exemplo para o diagrama apresentado está disponível link:modelagem[aqui]. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão. - -=== Princípios utilizados - -- https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)]: separa as partes que mudam (as operações primitivas/comportamentos) de dentro da classe que as utiliza. Isto torna a classe "aberta para extensão e fechada para modificação" (em relação aos comportamentos). -- https://en.wikipedia.org/wiki/Single_responsibility_principle[Single Responsibility Principle (SRP)]: a classe que usa os comportamentos não tem a responsabilidade de implementar estes comportamentos. - -=== Exemplo: Leitura de Retorno de Boletos - -pass:[] - -Anteriormente aplicamos o padrão link:../strategy[Strategy] para implementar a leitura de retorno de boletos bancários. -Como pudemos perceber, o código do método que lê arquivos do Banco do Brasil é muito parecido com o do Bradesco, havendo -muita duplicação de código. Neste caso, podemos adicionalmente aplicar o padrão Template Method para definir uma estrutura comum -para o algoritmo de leitura de arquivos de retorno, isolando as partes que alteram em métodos nas subclasses. - -O código fonte do projeto convencional para leitura de arquivos de retorno está disponível link:retorno-boleto-template[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/template-method/retorno-boleto-template[zip]). Tente primeiro fazer sua implementação a partir da leitura do diagrama, para depois analisar o código disponibilizado. - -pass:[] - -=== Strategy + Template Method - -Você pode ter percebido que a modelagem do Template Method usa herança, -indo contra a recomendação de https://en.wikipedia.org/wiki/Composition_over_inheritance[Favorecer Composição no lugar de Herança]. E se analisarmos tudo que foi abordado no padrão link:../strategy/[Strategy], composição traz flexibilidade. - -Então, se precisarmos trocar a implementação do algoritmo específico de leitura de arquivos de retorno -de um banco por outro, podemos aplicar o padrão Strategy em conjunto com o Template Method. -Mas neste caso, o algoritmo a ser trocado é apenas uma parte específica -de todo o algoritmo de processamento de tais arquivos. -Isto porque, a parte de leitura do arquivo não muda, apenas -como os dados são extraídos de cada linha obtida que sim. - -// O projeto link:retorno-boleto-template-and-strategy[retorno-boleto-template-and-strategy] mostra uma implementação puramente OO que une os dois padrões. (projeto apenas no repo local) - -=== Modelagem utilizando Programação Funcional - -A modelagem do padrão utilizando programação funcional é extremamente simples. -Teremos apenas uma classe concreta (no lugar de abstrata) e não necessariamente precisaremos de sub-classes. -Assim, o diagrama básico é apenas uma única classe como abaixo. - -image:template-method-funcional.png[] - -O `templateMethod()` então deve chamar as operações primitivas internamente. Estas são definidas como atributos do tipo `Function` (por exemplo), -indicando que eles armazenam a implementação de uma função. É a mesma lógica que utilizamos para o link:../strategy/retorno-boleto-funcional[projeto funcional para o padrão Strategy]. - -O código fonte do projeto funcional para leitura de arquivos de retorno está disponível link:retorno-boleto-template-funcional[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/template-method/retorno-boleto-template-funcional[zip]). - -== Modelagem convencional **SEM** o padrão Template Method - -Uma modelagem convencional que não utiliza o Template Method é normalmente modelada como apresentado no diagrama a seguir. - -image:no-template-method.png[] - -Utilizando o padrão: - -- `method()` na superclasse é concreto; -- as operações primitivas serão abstratas na superclasse e terão comportamentos diferentes em cada subclasse. - -Sem utilizar o padrão (como é mostrado acima): - -- temos apenas o `method()` que é abstrato na superclasse e terão comportamentos diferentes em cada subclasse; -- não temos operações primitivas. - -Como já discutido, isso leva à duplicação de código quando as implementações do `method()` em cada subclasse mudam em apenas algumas partes. -Caso as subclasses precisem apenas estender o `method()` da superclasse (adicionando operações no início ou no final do método), -podemos definir uma implementação base na superclasse e apenas estender o método nas subclasses. -Isto poderia ser implementado em uma subclasse simplesmente com o código abaixo: - -// tag::method-override[] -[source,java,linenums] ----- -public SubClasse1 extends ClasseAbstrata { - @Override - public TipoRetorno method(){ - TipoRetorno valor = super.method(); - operacaoPrimitiva1(); - operacaoPrimitiva2(); - operacaoPrimitivaN(); - - return valor; - } -} ----- -// end::method-override[] - -Neste caso, estamos estendendo o método apenas executando algumas operações depois da chamada do método na superclasse. -Poderíamos também executar tais operações antes e/ou depois, de acordo com as necessidades, como: - -[source,java,linenums] ----- -public SubClasse1 extends ClasseAbstrata { - @Override - public TipoRetorno method(){ - operacaoPrimitiva1(); - operacaoPrimitiva2(); - TipoRetorno valor = super.method(); - operacaoPrimitivaN(); - - return valor; - } -} ----- - -No entanto, o algoritmo base definido no `method()` na superclasse pode ser completamente modificado por qualquer subclasse, -o que normalmente é algo indesejado. Podemos fazer isso apenas eliminando a chamada `super.method()`. -Para isto, poderíamos simplesmente definir o `method()` na superclasse como `final`, -indicando que o método não pode ser sobrescrito nas subclasses. -Por outro lado, tal abordagem impede que as subclasses possam incluir mais operações como mostrado acima. - -Adicionalmente, com a abordagem acima, não temos como garantir que cada operação primitiva será incluída nas subclasses -no exato local onde elas precisam ser executadas ou se mesmo todas as operações esperadas serão incluídas, -o que pode gerar erros e resultados incorretos. -Por exemplo, imagine que a `operacaoPrimitiva2()` precisasse: - -- adicionar conteúdo em um arquivo que só seria criado após a chamada de `super.method()`; -- ou usar um valor retornado pelo `super.method()`. - -Com a implementação mostrada acima, não temos como garantir nada disso. -Logo, temos que recorrer ao padrão Template Method. - -== Detalhes de Implementação - -Dependendo de como você implementar o padrão, deverá estar atento a alguns detalhes. -Em qualquer implementação, uma subclasse pode subescrever tal método e mudar completamente toda a implementação do algoritmo, o que é algo que normalmente queremos evitar quando usamos o padrão. Isto foi discutido na seção acima para a implementação sem o padrão. - -No entanto, como as partes do algoritmo que alteram foram isoladas nas operações primitivas, as subclasses não devem modificar o `templateMethod()` na superclasse (veja o primeiro diagrama). Assim, com o padrão podemos definir o `templateMethod()` como `final` (o que não podemos sem o padrão). Isto impede que subclasses possam alterar a implementação dele, mas somente das operações primitivas. - -== Padrões Relacionados - -Padrões que possuem similaridades ou podem ser usados em conjunto: - -- link:../strategy[Strategy] -- Command - -== Onde o padrão é usado no JDK - -Os seguintes métodos não abstratos nas classe abaixo são exemplos de uso do Template Method no JDK: - -- `AbstractList.add`, `AbstractList.addAll`, `AbstractMap.putAll` -- `InputStream.read`, `OutputStream.write`, `Reader.read` e `Writer.write`. - -== Exercícios - -=== Strategy x Template Method - -Qual a diferença entre Strategy e Template Method, já que os dois estão relacionados à estrutura para implementação de algoritmos? - -=== Processo de finalização de uma compra - -Considere um sistema de loja onde você pode comprar vários itens. -Do ponto de vista da loja, é então registrada uma venda que pode possuir vários itens. -Ao finalizar tal venda, algumas operações devem ser finalizadas: - -1. reservar produto no estoque (para impedir que seja vendido para outro usuário); -2. realizar pagamento; -3. emitir nota fiscal; -4. encaminhar solicitação para próximo setor responsável. - -Dependendo se o cliente está na loja física ou virtual, -algumas etapas do processo de finalização da venda podem ser diferentes ou nem existirem. - -Se o cliente está na loja virtual, o processo de realização do pagamento deve ser feito online, -a partir da geração de um boleto bancário ou pelo número do cartão de crédito. - -Se estiver na loja física, o pagamento pode ser por: - -- dinheiro; -- carnê para pagamento na loja ou boleto (nos dois casos, não requer dados adicionais do cliente pois tudo deve estar no cadastro dele); -- cartão de crédito/débito físico, que deve ser inserido na máquina de cartão e o sistema deve aguardar a confirmação da compra pela máquina. - -A emissão da nota fiscal deve obrigatoriamente ser eletrônica atualmente. No entanto, -se a venda for pela loja física, caso o cliente não tenha email cadastrado, a nota é gerada mas não é enviada a ele. -Adicionalmente, o sistema deve solicitar a impressão da nota para entrega ao cliente. - -Por fim, o setor para o qual o trâmite após a venda deve seguir também muda, de acordo com a loja em que o cliente está. -Na loja virtual, o pedido deve ser enviado para o setor de separação de produtos, -enquanto na loja física deve ser enviado para o setor de entrega de produtos. - -A partir do diagrama abaixo, implemente as classes apresentadas aplicando o padrão Template Method. -Observe que apenas os relacionamentos foram definidos. Os métodos e atributos devem ser definidos por você. -Os atributos não tem importância para a implementação do padrão. Assim, defina apenas o que for -necessário para a sua implementação. - -image:template-method-venda.png[] - - diff --git a/comportamentais/02-template-method/README.html b/comportamentais/02-template-method/README.html new file mode 100644 index 000000000..86bdc210b --- /dev/null +++ b/comportamentais/02-template-method/README.html @@ -0,0 +1,806 @@ + + + + + + + +Padrões de Projetos Comportamentais + + + + + + + +
+
+

1. Template Method (Método Modelo) template

+
+ +
+

1.1. Definição

+
+

📘"Especifica o esqueleto de um algoritmo dentro de um método, transferindo alguns de seus passos pras subclasses. Permite que as subclasses alterem certos passos do algoritmo sem alterar a estrutura dele." [UCPP]

+
+
+
+

1.2. Aplicabilidade

+
+

Pode ser aplicado quando:

+
+
+
    +
  • +

    um método (algoritmo) possuir determinados passos definidos mas outros não; a implementação destes outros passos variar de uma subclasse para outra.

    +
  • +
  • +

    você começar a implementar um método em diversas subclasses e verificar que existem partes comuns (código duplicado) e outras partes que mudam de uma subclasse para outra.

    +
  • +
+
+
+
+

1.3. Modelagem do Padrão

+
+

template method base

+
+
+

A classe que implementará o Template Method realmente deve ser uma classe abstrata ou uma interface do Java 8+ com um método default (que possui implementação). No diagrama, o templateMethod() é que implementa o padrão. Ele que define a estrutudo do algoritmo a ser implementado. +Os métodos como operacaoPrimitivaN() são então métodos abstratos, que definem parte da implementação do algoritmo do templateMethod(). +Tais operações primitivas são então chamadas em algum lugar dentro do templateMethod(). +Cada subclasse pode ter sua própria implementação de cada uma destas operações.

+
+
+

Um projeto de exemplo para o diagrama apresentado está disponível aqui. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão.

+
+
+
+

1.4. Princípios utilizados

+
+
    +
  • +

    Open/Closed Principle (OCP): separa as partes que mudam (as operações primitivas/comportamentos) de dentro da classe que as utiliza. Isto torna a classe "aberta para extensão e fechada para modificação" (em relação aos comportamentos).

    +
  • +
  • +

    Single Responsibility Principle (SRP): a classe que usa os comportamentos não tem a responsabilidade de implementar estes comportamentos.

    +
  • +
+
+
+
+

1.5. Exemplo: Leitura de Retorno de Boletos

+
+

+
+
+

Anteriormente aplicamos o padrão Strategy para implementar a leitura de retorno de boletos bancários. +Como pudemos perceber, o código do método que lê arquivos do Banco do Brasil é muito parecido com o do Bradesco, havendo +muita duplicação de código. Neste caso, podemos adicionalmente aplicar o padrão Template Method para definir uma estrutura comum +para o algoritmo de leitura de arquivos de retorno, isolando as partes que alteram em métodos nas subclasses.

+
+
+

O código fonte do projeto convencional para leitura de arquivos de retorno está disponível aqui (zip). Tente primeiro fazer sua implementação a partir da leitura do diagrama, para depois analisar o código disponibilizado.

+
+
+

+
+
+
+

1.6. Strategy + Template Method

+
+

Você pode ter percebido que a modelagem do Template Method usa herança, +indo contra a recomendação de Favorecer Composição no lugar de Herança. E se analisarmos tudo que foi abordado no padrão Strategy, composição traz flexibilidade.

+
+
+

Então, se precisarmos trocar a implementação do algoritmo específico de leitura de arquivos de retorno +de um banco por outro, podemos aplicar o padrão Strategy em conjunto com o Template Method. +Mas neste caso, o algoritmo a ser trocado é apenas uma parte específica +de todo o algoritmo de processamento de tais arquivos. +Isto porque, a parte de leitura do arquivo não muda, apenas +como os dados são extraídos de cada linha obtida que sim.

+
+
+
+

1.7. Modelagem utilizando Programação Funcional

+
+

A modelagem do padrão utilizando programação funcional é extremamente simples. +Teremos apenas uma classe concreta (no lugar de abstrata) e não necessariamente precisaremos de sub-classes. +Assim, o diagrama básico é apenas uma única classe como abaixo.

+
+
+

template method funcional

+
+
+

O templateMethod() então deve chamar as operações primitivas internamente. Estas são definidas como atributos do tipo Function (por exemplo), +indicando que eles armazenam a implementação de uma função. É a mesma lógica que utilizamos para o projeto funcional para o padrão Strategy.

+
+
+

O código fonte do projeto funcional para leitura de arquivos de retorno está disponível aqui (zip).

+
+
+
+
+
+

2. Modelagem convencional SEM o padrão Template Method

+
+
+

Uma modelagem convencional que não utiliza o Template Method é normalmente modelada como apresentado no diagrama a seguir.

+
+
+

no template method

+
+
+

Utilizando o padrão:

+
+
+
    +
  • +

    method() na superclasse é concreto;

    +
  • +
  • +

    as operações primitivas serão abstratas na superclasse e terão comportamentos diferentes em cada subclasse.

    +
  • +
+
+
+

Sem utilizar o padrão (como é mostrado acima):

+
+
+
    +
  • +

    temos apenas o method() que é abstrato na superclasse e terão comportamentos diferentes em cada subclasse;

    +
  • +
  • +

    não temos operações primitivas.

    +
  • +
+
+
+

Como já discutido, isso leva à duplicação de código quando as implementações do method() em cada subclasse mudam em apenas algumas partes. +Caso as subclasses precisem apenas estender o method() da superclasse (adicionando operações no início ou no final do método), +podemos definir uma implementação base na superclasse e apenas estender o método nas subclasses. +Isto poderia ser implementado em uma subclasse simplesmente com o código abaixo:

+
+
+
+
public SubClasse1 extends ClasseAbstrata {
+    @Override
+    public TipoRetorno method(){
+        TipoRetorno valor = super.method();
+        operacaoPrimitiva1();
+        operacaoPrimitiva2();
+        operacaoPrimitivaN();
+
+        return valor;
+    }
+}
+
+
+
+

Neste caso, estamos estendendo o método apenas executando algumas operações depois da chamada do método na superclasse. +Poderíamos também executar tais operações antes e/ou depois, de acordo com as necessidades, como:

+
+
+
+
public SubClasse1 extends ClasseAbstrata {
+    @Override
+    public TipoRetorno method(){
+        operacaoPrimitiva1();
+        operacaoPrimitiva2();
+        TipoRetorno valor = super.method();
+        operacaoPrimitivaN();
+
+        return valor;
+    }
+}
+
+
+
+

No entanto, o algoritmo base definido no method() na superclasse pode ser completamente modificado por qualquer subclasse, +o que normalmente é algo indesejado. Podemos fazer isso apenas eliminando a chamada super.method(). +Para isto, poderíamos simplesmente definir o method() na superclasse como final, +indicando que o método não pode ser sobrescrito nas subclasses. +Por outro lado, tal abordagem impede que as subclasses possam incluir mais operações como mostrado acima.

+
+
+

Adicionalmente, com a abordagem acima, não temos como garantir que cada operação primitiva será incluída nas subclasses +no exato local onde elas precisam ser executadas ou se mesmo todas as operações esperadas serão incluídas, +o que pode gerar erros e resultados incorretos. +Por exemplo, imagine que a operacaoPrimitiva2() precisasse:

+
+
+
    +
  • +

    adicionar conteúdo em um arquivo que só seria criado após a chamada de super.method();

    +
  • +
  • +

    ou usar um valor retornado pelo super.method().

    +
  • +
+
+
+

Com a implementação mostrada acima, não temos como garantir nada disso. +Logo, temos que recorrer ao padrão Template Method.

+
+
+
+
+

3. Detalhes de Implementação

+
+
+

Dependendo de como você implementar o padrão, deverá estar atento a alguns detalhes. +Em qualquer implementação, uma subclasse pode subescrever tal método e mudar completamente toda a implementação do algoritmo, o que é algo que normalmente queremos evitar quando usamos o padrão. Isto foi discutido na seção acima para a implementação sem o padrão.

+
+
+

No entanto, como as partes do algoritmo que alteram foram isoladas nas operações primitivas, as subclasses não devem modificar o templateMethod() na superclasse (veja o primeiro diagrama). Assim, com o padrão podemos definir o templateMethod() como final (o que não podemos sem o padrão). Isto impede que subclasses possam alterar a implementação dele, mas somente das operações primitivas.

+
+
+
+
+

4. Padrões Relacionados

+
+
+

Padrões que possuem similaridades ou podem ser usados em conjunto:

+
+
+ +
+
+
+
+

5. Onde o padrão é usado no JDK

+
+
+

Os seguintes métodos não abstratos nas classe abaixo são exemplos de uso do Template Method no JDK:

+
+
+
    +
  • +

    AbstractList.add, AbstractList.addAll, AbstractMap.putAll

    +
  • +
  • +

    InputStream.read, OutputStream.write, Reader.read e Writer.write.

    +
  • +
+
+
+
+
+

6. Exercícios

+
+
+

6.1. Strategy x Template Method

+
+

Qual a diferença entre Strategy e Template Method, já que os dois estão relacionados à estrutura para implementação de algoritmos?

+
+
+
+

6.2. Processo de finalização de uma compra

+
+

Considere um sistema de loja onde você pode comprar vários itens. +Do ponto de vista da loja, é então registrada uma venda que pode possuir vários itens. +Ao finalizar tal venda, algumas operações devem ser finalizadas:

+
+
+
    +
  1. +

    reservar produto no estoque (para impedir que seja vendido para outro usuário);

    +
  2. +
  3. +

    realizar pagamento;

    +
  4. +
  5. +

    emitir nota fiscal;

    +
  6. +
  7. +

    encaminhar solicitação para próximo setor responsável.

    +
  8. +
+
+
+

Dependendo se o cliente está na loja física ou virtual, +algumas etapas do processo de finalização da venda podem ser diferentes ou nem existirem.

+
+
+

Se o cliente está na loja virtual, o processo de realização do pagamento deve ser feito online, +a partir da geração de um boleto bancário ou pelo número do cartão de crédito.

+
+
+

Se estiver na loja física, o pagamento pode ser por:

+
+
+
    +
  • +

    dinheiro;

    +
  • +
  • +

    carnê para pagamento na loja ou boleto (nos dois casos, não requer dados adicionais do cliente pois tudo deve estar no cadastro dele);

    +
  • +
  • +

    cartão de crédito/débito físico, que deve ser inserido na máquina de cartão e o sistema deve aguardar a confirmação da compra pela máquina.

    +
  • +
+
+
+

A emissão da nota fiscal deve obrigatoriamente ser eletrônica atualmente. No entanto, +se a venda for pela loja física, caso o cliente não tenha email cadastrado, a nota é gerada mas não é enviada a ele. +Adicionalmente, o sistema deve solicitar a impressão da nota para entrega ao cliente.

+
+
+

Por fim, o setor para o qual o trâmite após a venda deve seguir também muda, de acordo com a loja em que o cliente está. +Na loja virtual, o pedido deve ser enviado para o setor de separação de produtos, +enquanto na loja física deve ser enviado para o setor de entrega de produtos.

+
+
+

A partir do diagrama abaixo, implemente as classes apresentadas aplicando o padrão Template Method. +Observe que apenas os relacionamentos foram definidos. Os métodos e atributos devem ser definidos por você. +Os atributos não tem importância para a implementação do padrão. Assim, defina apenas o que for +necessário para a sua implementação.

+
+
+

template method venda

+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/02-template-method/index.html b/comportamentais/02-template-method/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/02-template-method/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/02-template-method/modelagem/README.adoc b/comportamentais/02-template-method/modelagem/README.adoc deleted file mode 100755 index b257727e8..000000000 --- a/comportamentais/02-template-method/modelagem/README.adoc +++ /dev/null @@ -1,7 +0,0 @@ -= Modelagem do Padrão Template Method (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/02-template-method/modelagem/[zip]) - -Apresenta um código de exemplo da modelagem do padrão Template Method. -Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. -Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos. - -image::../images/template-method-base.png[] diff --git a/comportamentais/02-template-method/modelagem/README.html b/comportamentais/02-template-method/modelagem/README.html new file mode 100644 index 000000000..28d18b0cc --- /dev/null +++ b/comportamentais/02-template-method/modelagem/README.html @@ -0,0 +1,459 @@ + + + + + + + +Modelagem do Padrão Template Method (zip) + + + + + +
+
+

Apresenta um código de exemplo da modelagem do padrão Template Method. +Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. +Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos.

+
+
+
+template method base +
+
+
+ + + \ No newline at end of file diff --git a/comportamentais/02-template-method/modelagem/index.html b/comportamentais/02-template-method/modelagem/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/02-template-method/modelagem/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/02-template-method/retorno-boleto-template-funcional/README.adoc b/comportamentais/02-template-method/retorno-boleto-template-funcional/README.adoc deleted file mode 100755 index 53ba57902..000000000 --- a/comportamentais/02-template-method/retorno-boleto-template-funcional/README.adoc +++ /dev/null @@ -1,18 +0,0 @@ -:imagesdir: ../images/ -:source-highlighter: highlightjs - -= Leitura de Retorno de Boletos Bancários usando implementação funcional do Template Method (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/02-template-method/retorno-boleto-template-funcional[zip]) - -Esta versão do projeto implementa a leitura de retorno de boletos com o padrão -Template Method, utilizando programação funcional. -Com tal implementação, evitamos a duplicação de código existente na versão anterior utilizando apenas -o padrão Strategy, conseguindo os mesmos efeitos de tal padrão: permitir trocar -a implementação de um algoritmo em tempo de execução. - -Por estar utilizando os dois padrões em conjunto, note que -a estrutura das classes não reflete exatamente os diagramas apresentados -na link:../[pasta anterior]. - -A modelagem desta implementação é mostrada abaixo. - -image::template-method-boleto-funcional.png[] diff --git a/comportamentais/02-template-method/retorno-boleto-template-funcional/README.html b/comportamentais/02-template-method/retorno-boleto-template-funcional/README.html new file mode 100644 index 000000000..e174a51ff --- /dev/null +++ b/comportamentais/02-template-method/retorno-boleto-template-funcional/README.html @@ -0,0 +1,477 @@ + + + + + + + +Leitura de Retorno de Boletos Bancários usando implementação funcional do Template Method (zip) + + + + + + +
+
+

Esta versão do projeto implementa a leitura de retorno de boletos com o padrão +Template Method, utilizando programação funcional. +Com tal implementação, evitamos a duplicação de código existente na versão anterior utilizando apenas +o padrão Strategy, conseguindo os mesmos efeitos de tal padrão: permitir trocar +a implementação de um algoritmo em tempo de execução.

+
+
+

Por estar utilizando os dois padrões em conjunto, note que +a estrutura das classes não reflete exatamente os diagramas apresentados +na pasta anterior.

+
+
+

A modelagem desta implementação é mostrada abaixo.

+
+
+
+template method boleto funcional +
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/02-template-method/retorno-boleto-template-funcional/index.html b/comportamentais/02-template-method/retorno-boleto-template-funcional/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/02-template-method/retorno-boleto-template-funcional/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/02-template-method/retorno-boleto-template-strategy/README.adoc b/comportamentais/02-template-method/retorno-boleto-template-strategy/README.adoc deleted file mode 100755 index 205ad9cd7..000000000 --- a/comportamentais/02-template-method/retorno-boleto-template-strategy/README.adoc +++ /dev/null @@ -1,21 +0,0 @@ -:imagesdir: ../images -:source-highlighter: highlightjs -:numbered: -:unsafe: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Leitura de arquivos de retorno de boletos bancários utilizando os Padrões Template Method e Strategy (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/02-template-method/retorno-boleto-template-and-strategy[zip]) - -Esta é a implementação da leitura de arquivos de retorno de boletos bancários utilizando o padrão Strategy em conjunto com Template Method. Veja a modelagem a seguir. - -image:template-method-strategy-boleto.png[] - -Este é um projeto que mostra como podemos adaptar padrões de acordo com nossas necessidades. Que tal criarmos um novo padrão chamado **Template Strategy**? 😎 diff --git a/comportamentais/02-template-method/retorno-boleto-template-strategy/README.html b/comportamentais/02-template-method/retorno-boleto-template-strategy/README.html new file mode 100644 index 000000000..f649bb7f3 --- /dev/null +++ b/comportamentais/02-template-method/retorno-boleto-template-strategy/README.html @@ -0,0 +1,466 @@ + + + + + + + +Leitura de arquivos de retorno de boletos bancários utilizando os Padrões Template Method e Strategy (zip) + + + + + + +
+
+

Esta é a implementação da leitura de arquivos de retorno de boletos bancários utilizando o padrão Strategy em conjunto com Template Method. Veja a modelagem a seguir.

+
+
+

template method strategy boleto

+
+
+

Este é um projeto que mostra como podemos adaptar padrões de acordo com nossas necessidades. Que tal criarmos um novo padrão chamado Template Strategy? 😎

+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/02-template-method/retorno-boleto-template-strategy/index.html b/comportamentais/02-template-method/retorno-boleto-template-strategy/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/02-template-method/retorno-boleto-template-strategy/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/02-template-method/retorno-boleto-template/README.adoc b/comportamentais/02-template-method/retorno-boleto-template/README.adoc deleted file mode 100755 index 89ec1257b..000000000 --- a/comportamentais/02-template-method/retorno-boleto-template/README.adoc +++ /dev/null @@ -1,10 +0,0 @@ -:imagesdir: ../images/ -:source-highlighter: highlightjs - -= Leitura de Retorno de Boletos Bancários usando Template Method (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/comportamentais/02-template-method/retorno-boleto-template[zip]) - -Esta versão do projeto implementa a leitura de retorno de boletos com o padrão -Template Method, evitando a duplicação de código existente na versão anterior utilizando apenas -o padrão Strategy. - -image::template-method-boleto.png[] diff --git a/comportamentais/02-template-method/retorno-boleto-template/README.html b/comportamentais/02-template-method/retorno-boleto-template/README.html new file mode 100644 index 000000000..ad637df80 --- /dev/null +++ b/comportamentais/02-template-method/retorno-boleto-template/README.html @@ -0,0 +1,467 @@ + + + + + + + +Leitura de Retorno de Boletos Bancários usando Template Method (zip) + + + + + + +
+
+

Esta versão do projeto implementa a leitura de retorno de boletos com o padrão +Template Method, evitando a duplicação de código existente na versão anterior utilizando apenas +o padrão Strategy.

+
+
+
+template method boleto +
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/02-template-method/retorno-boleto-template/index.html b/comportamentais/02-template-method/retorno-boleto-template/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/02-template-method/retorno-boleto-template/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/02-template-method/slides.adoc b/comportamentais/02-template-method/slides.adoc deleted file mode 100644 index 682df164a..000000000 --- a/comportamentais/02-template-method/slides.adoc +++ /dev/null @@ -1,238 +0,0 @@ -//:revealjsdir: https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.8.0/ -:revealjsdir: https://unpkg.com/reveal.js@4.3.1 -:revealjs_slideNumber: true -:revealjs_navigationMode: linear - -:source-highlighter: highlightjs -:icons: font -:allow-uri-read: -:stylesheet: ../../adoc-golo.css -:customcss: ../../slides-base.css -:numbered: - -:proj-boleto-template: retorno-boleto-template/src/main/java/com/manoelcampos/retornoboleto/ -:proj-boleto-strategy: ../strategy/retorno-boleto/src/main/java/com/manoelcampos/retornoboleto/LeituraRetornoBancoBrasil.java -:proj-boleto-template-strategy: retorno-boleto-template-strategy/src/main/java/com/manoelcampos/retornoboleto -:proj-boleto-funcional: retorno-boleto-template-funcional/src/main/java/com/manoelcampos/retornoboleto/ - -ifdef::env-github[] -//Exibe ícones para os blocos como NOTE e IMPORTANT no GitHub - -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -:chapter-label: -:listing-caption: Listagem -:figure-caption: Figura - -//Transição para todos os slides // none/fade/slide/convex/concave/zoom -//:revealjs_transition: 'zoom' - -//https://github.com/hakimel/reveal.js#theming -:revealjs_theme: league - -= Template Method image:images/template-large.png[link=https://www.flaticon.com/authors/monkik] - -Quase tudo que precisa saber - -Prof. Manoel Campos - -image::https://manoelcampos.com/padroes-projetos/images/biolink.png[] - -[transition=zoom] -== Categoria - -Padrão de projeto Comportamental image:../../images/behaviour.gif[] - -[transition=fade] -== Definição - -include::README.adoc[tag=definicao] - -image:../../images/ucpp.jpg[size=contain] - -[transition=zoofadem] -== Aplicabilidade - -Pode ser aplicado quando: - -[%step] -include::README.adoc[tag=aplicabilidade] - -[transition=zoom] -== Modelagem do Template Method - -=== ! - -image::images/template-method-base.png[background, size=contain] - -[transition=zoom] -== Mas consigo fazer isso apenas com herança e sobrescrita de método 🤨 - -include::README.adoc[tag=method-override] - -[transition=zoom, background-opacity=0.4] -== Princípios utilizados - -image::../../images/recommendations.jpg[background, size=contain, text=https://www.smart-energy.com, link=https://www.smart-energy.com/industry-sectors/smart-energy/five-key-recommendations-for-the-sustainable-energy-sector-growth-in-mena/] - -[%step] -- https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)] -- https://en.wikipedia.org/wiki/Single_responsibility_principle[Single Responsibility Principle (SRP)] - -[transition=zoom] -== ! - -- **Exemplo**: Leitura de arquivos de retorno de boletos bancários, de novo 😅. - -image::images/boleto-iugu-lp.png[background] - -== Problema da versão com Strategy - -=== ! - -[source,java,linenums] ----- -include::{proj-boleto-strategy}[tag=class-start] - /* Omitidos campos por simplificação */ -include::{proj-boleto-strategy}[tag=class-end] ----- - -== Modelagem do Retorno Boleto com Template Method - -image::images/template-method-boleto.png[background, size=contain] - -== Implementação do Retorno Boleto com Template Method - -=== Super classe - -[source,java,linenums] ----- -include::{proj-boleto-template}/ProcessadorBoletos.java[tag=class-start] -include::{proj-boleto-template}/ProcessadorBoletos.java[tag=template-method] -include::{proj-boleto-template}/ProcessadorBoletos.java[tag=primitive-operation] -include::{proj-boleto-template}/ProcessadorBoletos.java[tag=class-end] ----- - -=== Sub classe - -[source,java,linenums] ----- -include::{proj-boleto-template}/LeituraRetornoBancoBrasil.java[tag=class-start] -include::{proj-boleto-template}/LeituraRetornoBancoBrasil.java[tag=primitive-operation-start] - /* Omitidos campos por simplificação */ -include::{proj-boleto-template}/LeituraRetornoBancoBrasil.java[tag=primitive-operation-end] -include::{proj-boleto-template}/LeituraRetornoBancoBrasil.java[tag=class-end] ----- - -=== Usando a implementação do BB image:images/bb.png[] - -[source,java,linenums] ----- -ProcessadorBoletos processador = new LeituraRetornoBancoBrasil(); -String nomeArquivo = "caminho-arquivo-retorno-boleto-banco-brasil.csv"; -processador.processar(nomeArquivo); ----- - -[transition=fade] -== Comparação com o Strategy - -[%step] -- Strategy https://en.wikipedia.org/wiki/Composition_over_inheritance[favorece composição no lugar de herança] 👍 -- Template Method usa apenas herança: perda da flexibilidade e dinamismo do Strategy 😒 -- Mas removeu a duplicação do código e dividiu mais ainda as responsabilidades 🙌🏼 - -[transition=fade] -== ! - -**QUE TAL JUNTAR O PODER DOS PADRÕES?** - -**Strategy + Template Method** - -image::images/power-union.jpg[background, size=contain, link="http://iberapa.com/sustainability/"] - -=== ! - -image::images/template-method-strategy-boleto.png[background, size=contain] - -=== Implementação do Retorno Boleto com Strategy + Template Method - -=== ! - -[source,java,linenums] ----- -include::{proj-boleto-template-strategy}/ProcessarBoletos.java[tag=processar] ----- - -=== Usando a nova implementação com Strategy + Template Method - -[source,java,linenums] ----- -ProcessadorBoletos processador = - new ProcessadorBoletos(new LeituraRetornoBancoBrasil()); -String nomeArquivo = "caminho-arquivo-retorno-boleto-banco-brasil.csv"; -processador.processar(nomeArquivo); ----- - -== Modelagem do Template Method com Programação Funcional em Java 8+ - -só isso? 😯 - -image::images/template-method-funcional.png[] - -== Retorno Boleto com Template Method e Programação Funcional em Java 8+ - -=== ! - -image::images/template-method-boleto-funcional.png[background, size=contain] - -=== Implementação do Retorno Boleto com Template Method e Programação Funcional em Java 8+ - -=== ! - -[source,java,linenums] ----- -include::{proj-boleto-funcional}/ProcessadorBoletos.java[tag=class-start] -include::{proj-boleto-funcional}/ProcessadorBoletos.java[tag=class-end] ----- - -=== ! - -[source,java,linenums] ----- -include::{proj-boleto-funcional}/LeituraRetorno.java[tag=class-start] -include::{proj-boleto-funcional}/LeituraRetorno.java[tag=method-start] - /* Omitidos campos por simplificação */ -include::{proj-boleto-funcional}/LeituraRetorno.java[tag=method-end] ----- - -=== Usando a implementação Funcional - -[source,java,linenums] ----- -ProcessadorBoletos processador = - new ProcessadorBoletos(LeituraRetorno::processarLinhaBancoBrasil); -String nomeArquivo = "caminho-arquivo-retorno-boleto-banco-brasil.csv"; -processador.processar(nomeArquivo); ----- - -== O que houve com o Strategy na implementação Funcional? - -(revendo a modelagem) - -=== ! - -image::images/template-method-boleto-funcional.png[background, size=contain] - -== ! - -**Referências** - -- “Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos”. 2006 [GoF]. -- “Use a Cabeça! Padrões de Projetos”, 2008 [UCPP]. -- “Agile software development principles, patterns, and practices”, Robert Martin, 2011. [ASDPPP] -- http://refactoring.guru (agora também em Português) diff --git a/comportamentais/02-template-method/slides.html b/comportamentais/02-template-method/slides.html new file mode 100644 index 000000000..57fd8123d --- /dev/null +++ b/comportamentais/02-template-method/slides.html @@ -0,0 +1,1099 @@ + + + + + + + +Template Method + + + + + + +
+
+
+
+

Quase tudo que precisa saber

+
+
+

Prof. Manoel Campos

+
+
+
+biolink +
+
+
+
+
+

1. Categoria

+
+
+

Padrão de projeto Comportamental behaviour

+
+
+
+
+

2. Definição

+
+
+

📘"Especifica o esqueleto de um algoritmo dentro de um método, transferindo alguns de seus passos pras subclasses. Permite que as subclasses alterem certos passos do algoritmo sem alterar a estrutura dele." [UCPP]

+
+
+

ucpp

+
+
+
+
+

3. Aplicabilidade

+
+
+

Pode ser aplicado quando:

+
+
+
    +
  • +

    um método (algoritmo) possuir determinados passos definidos mas outros não; a implementação destes outros passos variar de uma subclasse para outra.

    +
  • +
  • +

    você começar a implementar um método em diversas subclasses e verificar que existem partes comuns (código duplicado) e outras partes que mudam de uma subclasse para outra.

    +
  • +
+
+
+
+
+

4. Modelagem do Template Method

+
+
+

4.1. !

+
+
+background +
+
+
+
+
+
+

5. Mas consigo fazer isso apenas com herança e sobrescrita de método 🤨

+
+
+
+
public SubClasse1 extends ClasseAbstrata {
+    @Override
+    public TipoRetorno method(){
+        TipoRetorno valor = super.method();
+        operacaoPrimitiva1();
+        operacaoPrimitiva2();
+        operacaoPrimitivaN();
+
+        return valor;
+    }
+}
+
+
+
+
+
+

6. Princípios utilizados

+ +
+
+

7. !

+
+
+
    +
  • +

    Exemplo: Leitura de arquivos de retorno de boletos bancários, de novo 😅.

    +
  • +
+
+
+
+background +
+
+
+
+
+

8. Problema da versão com Strategy

+
+
+

8.1. !

+
+
+
Unresolved directive in slides.adoc - include::../strategy/retorno-boleto/src/main/java/com/manoelcampos/retornoboleto/LeituraRetornoBancoBrasil.java[tag=class-start]
+                /* Omitidos campos por simplificação */
+Unresolved directive in slides.adoc - include::../strategy/retorno-boleto/src/main/java/com/manoelcampos/retornoboleto/LeituraRetornoBancoBrasil.java[tag=class-end]
+
+
+
+
+
+
+

9. Modelagem do Retorno Boleto com Template Method

+
+
+
+background +
+
+
+
+
+

10. Implementação do Retorno Boleto com Template Method

+
+
+

10.1. Super classe

+
+
+
public abstract class ProcessadorBoletos {
+    public final List<Boleto> processar(URI nomeArquivo){
+        try {
+            var listaLinhas = Files.readAllLines(Paths.get(nomeArquivo));
+            var boletos = new ArrayList<Boleto>();
+            for (String linha : listaLinhas) {
+                String[] vetor = linha.split(";");
+                var boleto = processarLinhaArquivo(vetor);
+                boletos.add(boleto);
+                System.out.println(boleto);
+            }
+
+            return boletos;
+        }catch(IOException ex){
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    protected abstract Boleto processarLinhaArquivo(String[] vetorLinhaArq);
+}
+
+
+
+
+

10.2. Sub classe

+
+
+
public class LeituraRetornoBancoBrasil extends ProcessadorBoletos {
+    @Override
+    protected Boleto processarLinhaArquivo(String[] vetorLinhaArq) {
+        Boleto boleto = new Boleto();
+        boleto.setId(Integer.parseInt(vetorLinhaArq[0]));
+        boleto.setCodBanco(vetorLinhaArq[1]);
+        /* Omitidos campos por simplificação */
+        boleto.setCpfCliente(vetorLinhaArq[4]);
+        boleto.setValor(Double.parseDouble(vetorLinhaArq[5]));
+        boleto.setMulta(Double.parseDouble(vetorLinhaArq[6]));
+        boleto.setJuros(Double.parseDouble(vetorLinhaArq[7]));
+        return boleto;
+    }
+}
+
+
+
+
+

10.3. Usando a implementação do BB bb

+
+
+
ProcessadorBoletos processador = new LeituraRetornoBancoBrasil();
+String nomeArquivo = "caminho-arquivo-retorno-boleto-banco-brasil.csv";
+processador.processar(nomeArquivo);
+
+
+
+
+
+
+

11. Comparação com o Strategy

+
+
+
    +
  • +

    Strategy favorece composição no lugar de herança 👍

    +
  • +
  • +

    Template Method usa apenas herança: perda da flexibilidade e dinamismo do Strategy 😒

    +
  • +
  • +

    Mas removeu a duplicação do código e dividiu mais ainda as responsabilidades 🙌🏼

    +
  • +
+
+
+
+
+

12. !

+
+
+

QUE TAL JUNTAR O PODER DOS PADRÕES?

+
+
+

Strategy + Template Method

+
+
+
+background +
+
+
+

12.1. !

+
+
+background +
+
+
+
+

12.2. Implementação do Retorno Boleto com Strategy + Template Method

+ +
+
+

12.3. !

+
+
+
        final var listaBoletos = new ArrayList<Boleto>();
+        try {
+            var listaLinhas = Files.readAllLines(Paths.get(caminhoArquivo));
+            for (String linha : listaLinhas) {
+                String[] vetor = linha.split(";");
+                final var boleto = leituraRetorno.processarLinhaArquivo(vetor);
+                listaBoletos.add(boleto);
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+
+
+
+
+

12.4. Usando a nova implementação com Strategy + Template Method

+
+
+
ProcessadorBoletos processador =
+        new ProcessadorBoletos(new LeituraRetornoBancoBrasil());
+String nomeArquivo = "caminho-arquivo-retorno-boleto-banco-brasil.csv";
+processador.processar(nomeArquivo);
+
+
+
+
+
+
+

13. Modelagem do Template Method com Programação Funcional em Java 8+

+
+
+

só isso? 😯

+
+
+
+template method funcional +
+
+
+
+
+

14. Retorno Boleto com Template Method e Programação Funcional em Java 8+

+
+
+

14.1. !

+
+
+background +
+
+
+
+

14.2. Implementação do Retorno Boleto com Template Method e Programação Funcional em Java 8+

+ +
+
+

14.3. !

+
+
+
public class ProcessadorBoletos {
+    private Function<String[], Boleto> processarLinhaArquivo;
+    
+    public ProcessadorBoletos(Function<String[], Boleto> processarLinhaArquivo){
+        this.processarLinhaArquivo = processarLinhaArquivo;
+    }
+
+    public final List<Boleto> processar(URI nomeArquivo){
+        try {
+            var listaLinhas = Files.readAllLines(Paths.get(nomeArquivo));
+            var boletos = new ArrayList<Boleto>();
+            for (String linha : listaLinhas) {
+                String[] vetor = linha.split(";");
+                var boleto = processarLinhaArquivo.apply(vetor);
+                boletos.add(boleto);
+                System.out.println(boleto);
+            }
+            return boletos;
+        }catch(IOException ex){
+            throw new UncheckedIOException(ex);
+        }
+    }
+}
+
+
+
+
+

14.4. !

+
+
+
public final class LeituraRetorno {
+    private LeituraRetorno(){
+        /*Não faz nada intencioalmente: a classe não deve ser instanciada.*/
+    }
+
+    public static Boleto processarLinhaBancoBrasil(String[] vetor) {
+        Boleto boleto = new Boleto();
+        boleto.setId(Integer.parseInt(vetor[0]));
+        boleto.setCodBanco(vetor[1]);
+        /* Omitidos campos por simplificação */
+        boleto.setCpfCliente(vetor[4]);
+        boleto.setValor(Double.parseDouble(vetor[5]));
+        boleto.setMulta(Double.parseDouble(vetor[6]));
+        boleto.setJuros(Double.parseDouble(vetor[7]));
+        return boleto;
+    }
+}
+
+
+
+
+

14.5. Usando a implementação Funcional

+
+
+
ProcessadorBoletos processador =
+        new ProcessadorBoletos(LeituraRetorno::processarLinhaBancoBrasil);
+String nomeArquivo = "caminho-arquivo-retorno-boleto-banco-brasil.csv";
+processador.processar(nomeArquivo);
+
+
+
+
+
+
+

15. O que houve com o Strategy na implementação Funcional?

+
+
+

(revendo a modelagem)

+
+
+

15.1. !

+
+
+background +
+
+
+
+
+
+

16. !

+
+
+

Referências

+
+
+
    +
  • +

    “Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos”. 2006 [GoF].

    +
  • +
  • +

    “Use a Cabeça! Padrões de Projetos”, 2008 [UCPP].

    +
  • +
  • +

    “Agile software development principles, patterns, and practices”, Robert Martin, 2011. [ASDPPP]

    +
  • +
  • +

    http://refactoring.guru (agora também em Português)

    +
  • +
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/README.adoc b/comportamentais/README.adoc deleted file mode 100644 index 88e0c8c90..000000000 --- a/comportamentais/README.adoc +++ /dev/null @@ -1,25 +0,0 @@ -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font -:imagesdir: ../images/ - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Comportamentais - -image::behaviour.gif[width=300] - -NOTE: https://www.youtube.com/watch?v=as8N4o2u0Lg&list=PLyo0RUAM69Us0FrSJYr2E_w-6bNlQY5GN[Playlist de Padrões Comportamentais no YouTube] - -- link:01-strategy[Strategy] -- link:02-template-method[Template Method] - -ifndef::env-github[image:back.png[alt=Voltar, link=../]] diff --git a/comportamentais/README.html b/comportamentais/README.html new file mode 100644 index 000000000..2315fd366 --- /dev/null +++ b/comportamentais/README.html @@ -0,0 +1,488 @@ + + + + + + + +Padrões de Projetos Comportamentais + + + + + + + +
+
+
+behaviour +
+
+ +
+ +
+
+

Voltar

+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/index.html b/comportamentais/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/comportamentais/observer/README.adoc b/comportamentais/observer/README.adoc deleted file mode 100755 index 63c7982dc..000000000 --- a/comportamentais/observer/README.adoc +++ /dev/null @@ -1,61 +0,0 @@ -:imagesdir: ../../images/patterns/estruturais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Comportamentais - -== Observer (Observador) - -- Também conhecido como Listener (Ouvinte) - -=== Definição - -"xxxx" <>. - -=== Aplicabilidade - -// Como frameworks two-way databinding como Angular aplicam o padrão para detectar alterações no modelo? - -=== Modelagem do Padrão - -// image:observer.png[] - -=== Princípios utilizados - - -=== Exemplos - -- Detectar eventos de componentes em uma interface gráfica, como o click de um botão ou pressionamento de tecla em um campo. -- Detectar alterações em um diretório https://www.baeldung.com/java-nio2-watchservice[<1>] https://docs.oracle.com/javase/tutorial/essential/io/notification.html[<2>] -- https://developer.android.com/reference/android/os/FileObserver[Observando mudanças em um arquivo em apps Android] - -== Exercícios - - -//=== Compactação de Arquivos para download - -//Implementar aplicação que realiza a compactação de arquivos de uma determinada pasta no servidor. -//Quando a compactação tiver sido finalizada, notificar o usuário, fornecendo um link para download. -// Implementar usando VRaptor. Ver classes de compactação de arquivos no WorkloadFileReader do CloudSim Plus. - -=== Modelagem utilizando Programação Funcional - - - -== Padrões Relacionados - - -== Onde o padrão é usado no JDK - - diff --git a/comportamentais/observer/README.html b/comportamentais/observer/README.html new file mode 100644 index 000000000..f26767fb4 --- /dev/null +++ b/comportamentais/observer/README.html @@ -0,0 +1,525 @@ + + + + + + + +Padrões de Projetos Comportamentais + + + + + + + +
+
+

1. Observer (Observador)

+
+
+
    +
  • +

    Também conhecido como Listener (Ouvinte)

    +
  • +
+
+
+

1.1. Definição

+
+

"xxxx" [UCPP].

+
+
+
+

1.2. Aplicabilidade

+ +
+
+

1.3. Modelagem do Padrão

+ +
+
+

1.4. Princípios utilizados

+ +
+
+

1.5. Exemplos

+
+ +
+
+
+
+
+

2. Exercícios

+
+
+

2.1. Modelagem utilizando Programação Funcional

+ +
+
+
+
+

3. Padrões Relacionados

+
+ +
+
+
+

4. Onde o padrão é usado no JDK

+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/comportamentais/observer/index.html b/comportamentais/observer/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/comportamentais/observer/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/01-simple-factory/README.adoc b/criacionais/01-simple-factory/README.adoc deleted file mode 100755 index 7e07ca063..000000000 --- a/criacionais/01-simple-factory/README.adoc +++ /dev/null @@ -1,222 +0,0 @@ -:imagesdir: ../../images/patterns/criacionais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Criacionais - -IMPORTANT: https://www.youtube.com/playlist?list=PLyo0RUAM69UtO8Jjq71qgvRxcI2pTrB2m[Vídeo-aulas disponíveis aqui.] - -== Simple Factory (Fábrica Simples) - -=== Definição - -📘Simple Factory permite encapsular a criação de objetos em uma classe que representa uma fábrica. -Ela não é de fato um padrão de projeto, podendo ser definida como um modelo para a criação de objetos. - -=== Aplicabilidade - -Sabemos que para instanciar objetos em Java e outras linguagens é utilizado o operador `new`. -Apesar de podermos declarar uma variável com um tipo abstrato, ao instanciar um objeto para tal variável, -estamos definindo explicitamente qual tipo concreto será usado. - -Se existir uma lógica que define qual tipo concreto será utilizado em um determinado momento e tivermos que -utilizar esta lógica em diversas partes do código quando precisarmos instanciar um objeto, podemos utilizar -a Simple Factory para encapsular a criação destes objetos. Com isto, evitamos de duplicar esta lógica em -vários locais do projeto. -Esta lógica normalmente é definida por um bloco de `if()` que define as condições para a criação dos objetos. - -Adicionalmente, considere que temos um tipo abstrato/super-tipo (classe abstrata ou interface) e várias sub-classes que podem ser instanciados. -Se utilizarmos `new` para instanciar uma determinada sub-classe em diferentes locais do sistema e precisarmos -substituir estas instâncias por uma sub-classe diferente, teríamos que fazer isso manualmente alterando -os vários locais no código. Utilizando a Simple Factory, a criação de objetos de uma determinada sub-classe -fica encapsulada e centralizada em um método da Simple Factory. - -=== Modelagem - -A Simple Factory pode ser modelada como demonstrado no diagrama a seguir. - -.Modelagem da Simple Factory -image::simple-factory.png[] - -Teremos uma classe `SimpleFactory` que você deve dar um nome apropriado. -Alguns exemplos incluem: - -- `SimplePizzaFactory` ou `PizzaFactory` para criar pizzas; -- `SimpleProdutoFactory` ou `ProdutoFactory` para criar produtos. - -`Cliente` é uma classe qualquer que precisa utilizar objetos produzidos pela Factory. -Assim, podemos ter várias classes clientes. - -NOTE: O termo "cliente", amplamente utilizado quando falamos de padrões de projeto e POO, representa uma classe que usa os serviços de outra classe, como uma pessoa que usa os serviços de uma empresa. - -O `TipoAbstrato` é um super tipo representado por uma **interface** ou **classe abstrata**. -Como ele é abstrato, a Factory criará objetos de algum dos sub-tipos disponíveis, -de acordo com uma possível lógica que você definir. - -Os métodos `newObject` da `SimpleFactory` retornam um `TipoAbstrato`, mas internamente -criam um objeto de algum dos sub-tipos existentes. Este método é normalmente definido como estático, -assim, não temos que instanciar a fábrica para depois podermos instanciar os objetos que queremos. -Observe que pode haver duas versões de tal método. A versão que não recebe parâmetros normalmente vai -sempre retornar um tipo específico de objeto. Ao usar tal método em várias partes do sistema, -se precisarmos trocar qual o tipo de objeto a ser instanciado, temos que apenas alterar este método. -Os locais onde ele estava sendo usado não sofrem nenhuma alteração. - -A outra versão do método que possui parâmetros (cujo quantidade e tipos depende do seu problema) -normalmente vai permitir, ao desenvolvedor que for usar a Factory, informar qual objeto -a ser criado e possíveis dados a serem usados para criá-lo, sem especificar -qual classe será instanciada. Adicionalmente, se existir uma determinada lógica necessária -para criar qualquer dos tipos de objeto possíveis, tal lógica ficará encapsulada -dentro destes métodos `newObject`. Qualquer alteração neste lógica precisará ser feita -em apenas um local. - -Um projeto de exemplo para o diagrama apresentado está disponível link:modelagem[aqui]. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão. - -=== Princípios utilizados - -==== Open-Closed Principle - -Com o https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)], separamos as partes que mudam, i.e. a lógica de criação de objetos, de dentro da classe que utiliza tais objetos. Isto torna a classe que utiliza a factory "aberta para extensão e fechada para modificação". - -==== Programar para uma "interface" não uma implementação - -https://tuhrig.de/programming-to-an-interface/[Programar para uma "interface" não uma implementação] (GoF) indica que devemos declar variáveis com tipos abstratos (`TipoAbstrato`) e usar tipos concretos apenas na instanciação (`SubTipo1` ... `SubTipoN`). - -==== Dependency Inversion Principle (DIP) - -Ao aplicar o https://en.wikipedia.org/wiki/Dependency_inversion_principle[Dependency Inversion Principle (DIP)], a classe cliente que utiliza a factory não depende mais de tipos concretos, mas sim de tipos abstratos (interfaces ou classes abstratas). -Se *não* utilizássemos a Simple Factory, a classe cliente seria responsável pela lógica de criação dos objetos, -dependendo de cada um dos objetos que pode criar, como mostra o diagrama a seguir. - -.Dependências com a NÃO utilização da Simple Factory -image::no-simple-factory.png[] - -Se observarmos a Figura 1 na Seção 1.3, podemos ver que a classe `Cliente` depende da `SimpleFactory`, que depende do `TipoAbstrato`. -Como `Cliente` usará objetos do `TipoAbstrato`, ele depende de tal tipo. Então, podemos esquecer a `SimpleFactory` por um momento e visualizar esta dependência como no diagrama a seguir. - -.Dependência com a utilização da Simple Factory: classe Cliente depende de TipoAbstrato -image::simple-factory-dip.png[] - -Comparando a Figura 2 com a 3, podemos ver que a relação de dependência foi invertida. A classe `Cliente` deixou de depender de tipos concretos e passou a depender de um tipo abstrato. - -=== Exemplos - -Podemos utilizar a Simple Factory para definir qual estratégia de leitura de arquivo de retorno de boleto bancário -será utilizada. Assim, não teremos que manualmente decidir qual estratégia instanciar cada vez que -precisarmos ler arquivos de retorno. -Baseado no projeto link:../../comportamentais/template-method/retorno-boleto-template-funcional[retorno-boleto-template-funcional], vamos implementar a Simple Factory. - -Implemente o projeto seguindo a modelagem abaixo: - -.Simple Factory para a instanciação de estratégias de processamento de arquivos de retorno de boleto bancário. -image::simple-factory-boleto-funcional.png[] - -O código fonte do projeto está disponível link:retorno-boleto-simple-factory[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/simple-factory/retorno-boleto-simple-factory[zip]). -Uma implementação alternativa, que não utiliza programação funcional e descobre dinamicamente o nome da -classe para leitura do arquivo de retorno informado pode ser vista link:retorno-boleto-simple-factory-dynamic[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/simple-factory/retorno-boleto-simple-factory-dynamic[zip]). -Veja a documentação no link acima para detalhes do projeto. - -=== Detalhes de Implementação - -A forma mais fácil de implementar a Simple Factory, como apresentado na Figura 1, é definir o método `newObject` na classe `SimpleFactory` como estático. -Assim, não é preciso instanciar uma fábrica para depois criar objetos, basta chamar o método diretamente da classe -fazendo `SimpleFactory.newObject()`. Isto torna o uso da fábrica mais fácil. -Se a fábrica não armazena nenhum atributo, pode não haver uma razão específica para exigir que ela seja instanciada -para podermos chamar seus métodos. É apenas preciso ter em mente que ao declarar o método como estático, -ele não poderá ser modificado em possíveis sub-classes. Se não pretende fazer override do método, não há problema. - -O método `newObject` também pode receber parâmetros para definir qual e/ou como um objeto será criado. -O nome do método também deve ser definido adequadamente, como `newPizza()`, `newProduto()`, etc. - -== Padrões Relacionados - -Padrões que possuem similaridades ou podem ser usados em conjunto: - -- link:../../comportamentais/template-method[Template Method] - -== Onde o padrão é usado no JDK - -=== Calendar - -A classe `Calendar` no JDK é abstrata, logo, não pode ser instanciada. -Existem diferentes tipos de calendário que podem ser instanciados, de acordo -com a região geográfica definida para o sistema (`Locale`). -O método `getInstance()` então é responsável por definir qual subclasse de `Calendar` -será usada para instanciar um calendário. - -Ele utiliza o método auxiliar `createCalendar` para isto. Como falado -anteriormente, neste caso o método possui parâmetros para definir como criar o objeto. -Note que dentro do método ele define diferentes tipos de calendário, como gregorianos (o nosso), japonês e budista. - -=== JCF no JDK 9+ - -A partir do JDK 9, as classes Collection introduziram os chamados -"Factory Methods". Apesar do nome ser o de outro padrão que veremos -à frente, tal padrão não é implementado aqui. O que temos é simplesmente -uma Simple Fatory. - -A expressão *Factory Method* expressão é confusa pois pode se referir à: - -- um padrão com este mesmo nome (não é o caso), que veremos a seguir; -- ou simplesmente a um *método fábrica* em uma classe/interface responsável por instanciar objetos. - Qualquer tipo de fábrica terá um método fábrica. - -[source, java] ----- -List listaNomes = List.of("Minha", "Lista", "de", "Strings"); ----- - -[source, java] ----- -Map mapaHabitantesCidade = - Map.of("Palmas", 217000, "Gurupi", 84000); ----- - -=== Falando de JDK, pula pro JDK 10 - -[source, java] ----- -var listaNomes = List.of("Minha", "Lista", "de", "Strings"); -var listaPares = List.of(2, 4, 6); -var mapaHabitantesCidade = Map.of("Palmas", 217000, "Gurupi", 84000); ----- - -== Exercícios - -pass:[] - -=== Exportação de dados - -Implemente um conjunto de classes que recebe uma lista de produtos e permite exportar tais produtos em diferentes formatos como Tabela HTML, CSV, tabela Markdown. Utilize a diagrama de classes abaixo como base para sua implementação. Tenha em mente que um diagrama desses pode apresentar os detalhes mais importantes como métodos e atributos que já se sabe previamente. No entanto, durante o desenvolvimento, pode-se -perceber que são necessários mais métodos e/ou atributos. O diagrama apresenta apenas os elementos públicos e protegidos. -Novos métodos que precisem ser incluídos, que serão usados pelos apresentados, normalmente são privados, -exatamente por serem apenas métodos auxiliares que não fazem sentido serem chamados de fora das classes. - -.Diagrama de classes para implementação do exportador de lista de produtos para HTML e Markdown -image::exportador-simple-factory.png[] - -Observe que neste caso, não temos uma classe específica para a Simple Factory. -Temos apenas os métodos estáticos `newInstance()` na interface `ExportadorListaProdutos` -que instanciam objetos da própria classe. Esta é a mesma modelagem utilizada pela classe `Calendar` -do JDK. Métodos estáticos em interfaces é um dos recursos do Java 8. - -NOTE: Existem inúmeras bibliotecas que realizam tal tarefa, mas o objetivo aqui é praticar. Se precisar realmente exportar dados em qualquer formato, tente utilizar uma biblioteca existente. Pode-se exportar dados em XML e JSON utilizando bibliotecas padrões do JDK. - -O código fonte do projeto está disponível link:exportador-simple-factory[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/simple-factory/exportador-simple-factory[zip]), mas tente primeiro implementar antes de ver o projeto. - -=== Tornando a exportação de dados genérica - -O projeto anterior permite exportar apenas uma lista de produtos. Se precisarmos exportar outros dados como clientes ou vendas, teremos que criar um novo conjunto de classes para cada tipo de objeto que queremos exportar. Isto é bastante trabalhoso e repetitivo. -Neste projeto vamos usar __Reflection__, um recurso avançado da linguagem Java, com o Simple Factory para conseguir exportar qualquer dado em qualquer formato implementado. - -O código fonte do projeto está disponível link:exportador-simple-factory-reflection[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/simple-factory/exportador-simple-factory-reflection[zip]), mas tente primeiro implementar antes de ver o projeto. diff --git a/criacionais/01-simple-factory/README.html b/criacionais/01-simple-factory/README.html new file mode 100644 index 000000000..37b7fa1d7 --- /dev/null +++ b/criacionais/01-simple-factory/README.html @@ -0,0 +1,790 @@ + + + + + + + +Padrões de Projetos Criacionais + + + + + + + +
+
+
+
+ + + + + +
+ + +Vídeo-aulas disponíveis aqui. +
+
+
+
+
+

1. Simple Factory (Fábrica Simples)

+
+
+

1.1. Definição

+
+

📘Simple Factory permite encapsular a criação de objetos em uma classe que representa uma fábrica. +Ela não é de fato um padrão de projeto, podendo ser definida como um modelo para a criação de objetos.

+
+
+
+

1.2. Aplicabilidade

+
+

Sabemos que para instanciar objetos em Java e outras linguagens é utilizado o operador new. +Apesar de podermos declarar uma variável com um tipo abstrato, ao instanciar um objeto para tal variável, +estamos definindo explicitamente qual tipo concreto será usado.

+
+
+

Se existir uma lógica que define qual tipo concreto será utilizado em um determinado momento e tivermos que +utilizar esta lógica em diversas partes do código quando precisarmos instanciar um objeto, podemos utilizar +a Simple Factory para encapsular a criação destes objetos. Com isto, evitamos de duplicar esta lógica em +vários locais do projeto. +Esta lógica normalmente é definida por um bloco de if() que define as condições para a criação dos objetos.

+
+
+

Adicionalmente, considere que temos um tipo abstrato/super-tipo (classe abstrata ou interface) e várias sub-classes que podem ser instanciados. +Se utilizarmos new para instanciar uma determinada sub-classe em diferentes locais do sistema e precisarmos +substituir estas instâncias por uma sub-classe diferente, teríamos que fazer isso manualmente alterando +os vários locais no código. Utilizando a Simple Factory, a criação de objetos de uma determinada sub-classe +fica encapsulada e centralizada em um método da Simple Factory.

+
+
+
+

1.3. Modelagem

+
+

A Simple Factory pode ser modelada como demonstrado no diagrama a seguir.

+
+
+
+simple factory +
+
Figure 1. Modelagem da Simple Factory
+
+
+

Teremos uma classe SimpleFactory que você deve dar um nome apropriado. +Alguns exemplos incluem:

+
+
+
    +
  • +

    SimplePizzaFactory ou PizzaFactory para criar pizzas;

    +
  • +
  • +

    SimpleProdutoFactory ou ProdutoFactory para criar produtos.

    +
  • +
+
+
+

Cliente é uma classe qualquer que precisa utilizar objetos produzidos pela Factory. +Assim, podemos ter várias classes clientes.

+
+
+ + + + + +
+ + +O termo "cliente", amplamente utilizado quando falamos de padrões de projeto e POO, representa uma classe que usa os serviços de outra classe, como uma pessoa que usa os serviços de uma empresa. +
+
+
+

O TipoAbstrato é um super tipo representado por uma interface ou classe abstrata. +Como ele é abstrato, a Factory criará objetos de algum dos sub-tipos disponíveis, +de acordo com uma possível lógica que você definir.

+
+
+

Os métodos newObject da SimpleFactory retornam um TipoAbstrato, mas internamente +criam um objeto de algum dos sub-tipos existentes. Este método é normalmente definido como estático, +assim, não temos que instanciar a fábrica para depois podermos instanciar os objetos que queremos. +Observe que pode haver duas versões de tal método. A versão que não recebe parâmetros normalmente vai +sempre retornar um tipo específico de objeto. Ao usar tal método em várias partes do sistema, +se precisarmos trocar qual o tipo de objeto a ser instanciado, temos que apenas alterar este método. +Os locais onde ele estava sendo usado não sofrem nenhuma alteração.

+
+
+

A outra versão do método que possui parâmetros (cujo quantidade e tipos depende do seu problema) +normalmente vai permitir, ao desenvolvedor que for usar a Factory, informar qual objeto +a ser criado e possíveis dados a serem usados para criá-lo, sem especificar +qual classe será instanciada. Adicionalmente, se existir uma determinada lógica necessária +para criar qualquer dos tipos de objeto possíveis, tal lógica ficará encapsulada +dentro destes métodos newObject. Qualquer alteração neste lógica precisará ser feita +em apenas um local.

+
+
+

Um projeto de exemplo para o diagrama apresentado está disponível aqui. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão.

+
+
+
+

1.4. Princípios utilizados

+
+

1.4.1. Open-Closed Principle

+
+

Com o Open/Closed Principle (OCP), separamos as partes que mudam, i.e. a lógica de criação de objetos, de dentro da classe que utiliza tais objetos. Isto torna a classe que utiliza a factory "aberta para extensão e fechada para modificação".

+
+
+
+

1.4.2. Programar para uma "interface" não uma implementação

+
+

Programar para uma "interface" não uma implementação (GoF) indica que devemos declar variáveis com tipos abstratos (TipoAbstrato) e usar tipos concretos apenas na instanciação (SubTipo1 …​ SubTipoN).

+
+
+
+

1.4.3. Dependency Inversion Principle (DIP)

+
+

Ao aplicar o Dependency Inversion Principle (DIP), a classe cliente que utiliza a factory não depende mais de tipos concretos, mas sim de tipos abstratos (interfaces ou classes abstratas). +Se não utilizássemos a Simple Factory, a classe cliente seria responsável pela lógica de criação dos objetos, +dependendo de cada um dos objetos que pode criar, como mostra o diagrama a seguir.

+
+
+
+no simple factory +
+
Figure 2. Dependências com a NÃO utilização da Simple Factory
+
+
+

Se observarmos a Figura 1 na Seção 1.3, podemos ver que a classe Cliente depende da SimpleFactory, que depende do TipoAbstrato. +Como Cliente usará objetos do TipoAbstrato, ele depende de tal tipo. Então, podemos esquecer a SimpleFactory por um momento e visualizar esta dependência como no diagrama a seguir.

+
+
+
+simple factory dip +
+
Figure 3. Dependência com a utilização da Simple Factory: classe Cliente depende de TipoAbstrato
+
+
+

Comparando a Figura 2 com a 3, podemos ver que a relação de dependência foi invertida. A classe Cliente deixou de depender de tipos concretos e passou a depender de um tipo abstrato.

+
+
+
+
+

1.5. Exemplos

+
+

Podemos utilizar a Simple Factory para definir qual estratégia de leitura de arquivo de retorno de boleto bancário +será utilizada. Assim, não teremos que manualmente decidir qual estratégia instanciar cada vez que +precisarmos ler arquivos de retorno. +Baseado no projeto retorno-boleto-template-funcional, vamos implementar a Simple Factory.

+
+
+

Implemente o projeto seguindo a modelagem abaixo:

+
+
+
+simple factory boleto funcional +
+
Figure 4. Simple Factory para a instanciação de estratégias de processamento de arquivos de retorno de boleto bancário.
+
+
+

O código fonte do projeto está disponível aqui (zip). +Uma implementação alternativa, que não utiliza programação funcional e descobre dinamicamente o nome da +classe para leitura do arquivo de retorno informado pode ser vista aqui (zip). +Veja a documentação no link acima para detalhes do projeto.

+
+
+
+

1.6. Detalhes de Implementação

+
+

A forma mais fácil de implementar a Simple Factory, como apresentado na Figura 1, é definir o método newObject na classe SimpleFactory como estático. +Assim, não é preciso instanciar uma fábrica para depois criar objetos, basta chamar o método diretamente da classe +fazendo SimpleFactory.newObject(). Isto torna o uso da fábrica mais fácil. +Se a fábrica não armazena nenhum atributo, pode não haver uma razão específica para exigir que ela seja instanciada +para podermos chamar seus métodos. É apenas preciso ter em mente que ao declarar o método como estático, +ele não poderá ser modificado em possíveis sub-classes. Se não pretende fazer override do método, não há problema.

+
+
+

O método newObject também pode receber parâmetros para definir qual e/ou como um objeto será criado. +O nome do método também deve ser definido adequadamente, como newPizza(), newProduto(), etc.

+
+
+
+
+
+

2. Padrões Relacionados

+
+
+

Padrões que possuem similaridades ou podem ser usados em conjunto:

+
+
+ +
+
+
+
+

3. Onde o padrão é usado no JDK

+
+
+

3.1. Calendar

+
+

A classe Calendar no JDK é abstrata, logo, não pode ser instanciada. +Existem diferentes tipos de calendário que podem ser instanciados, de acordo +com a região geográfica definida para o sistema (Locale). +O método getInstance() então é responsável por definir qual subclasse de Calendar +será usada para instanciar um calendário.

+
+
+

Ele utiliza o método auxiliar createCalendar para isto. Como falado +anteriormente, neste caso o método possui parâmetros para definir como criar o objeto. +Note que dentro do método ele define diferentes tipos de calendário, como gregorianos (o nosso), japonês e budista.

+
+
+
+

3.2. JCF no JDK 9+

+
+

A partir do JDK 9, as classes Collection introduziram os chamados +"Factory Methods". Apesar do nome ser o de outro padrão que veremos +à frente, tal padrão não é implementado aqui. O que temos é simplesmente +uma Simple Fatory.

+
+
+

A expressão Factory Method expressão é confusa pois pode se referir à:

+
+
+
    +
  • +

    um padrão com este mesmo nome (não é o caso), que veremos a seguir;

    +
  • +
  • +

    ou simplesmente a um método fábrica em uma classe/interface responsável por instanciar objetos. +Qualquer tipo de fábrica terá um método fábrica.

    +
  • +
+
+
+
+
List<String> listaNomes = List.of("Minha", "Lista", "de", "Strings");
+
+
+
+
+
Map<String, Integer> mapaHabitantesCidade =
+                        Map.of("Palmas", 217000, "Gurupi", 84000);
+
+
+
+
+

3.3. Falando de JDK, pula pro JDK 10

+
+
+
var listaNomes = List.of("Minha", "Lista", "de", "Strings");
+var listaPares = List.of(2, 4, 6);
+var mapaHabitantesCidade = Map.of("Palmas", 217000, "Gurupi", 84000);
+
+
+
+
+
+
+

4. Exercícios

+
+
+

+
+
+

4.1. Exportação de dados

+
+

Implemente um conjunto de classes que recebe uma lista de produtos e permite exportar tais produtos em diferentes formatos como Tabela HTML, CSV, tabela Markdown. Utilize a diagrama de classes abaixo como base para sua implementação. Tenha em mente que um diagrama desses pode apresentar os detalhes mais importantes como métodos e atributos que já se sabe previamente. No entanto, durante o desenvolvimento, pode-se +perceber que são necessários mais métodos e/ou atributos. O diagrama apresenta apenas os elementos públicos e protegidos. +Novos métodos que precisem ser incluídos, que serão usados pelos apresentados, normalmente são privados, +exatamente por serem apenas métodos auxiliares que não fazem sentido serem chamados de fora das classes.

+
+
+
+exportador simple factory +
+
Figure 5. Diagrama de classes para implementação do exportador de lista de produtos para HTML e Markdown
+
+
+

Observe que neste caso, não temos uma classe específica para a Simple Factory. +Temos apenas os métodos estáticos newInstance() na interface ExportadorListaProdutos +que instanciam objetos da própria classe. Esta é a mesma modelagem utilizada pela classe Calendar +do JDK. Métodos estáticos em interfaces é um dos recursos do Java 8.

+
+
+ + + + + +
+ + +Existem inúmeras bibliotecas que realizam tal tarefa, mas o objetivo aqui é praticar. Se precisar realmente exportar dados em qualquer formato, tente utilizar uma biblioteca existente. Pode-se exportar dados em XML e JSON utilizando bibliotecas padrões do JDK. +
+
+
+

O código fonte do projeto está disponível aqui (zip), mas tente primeiro implementar antes de ver o projeto.

+
+
+
+

4.2. Tornando a exportação de dados genérica

+
+

O projeto anterior permite exportar apenas uma lista de produtos. Se precisarmos exportar outros dados como clientes ou vendas, teremos que criar um novo conjunto de classes para cada tipo de objeto que queremos exportar. Isto é bastante trabalhoso e repetitivo. +Neste projeto vamos usar Reflection, um recurso avançado da linguagem Java, com o Simple Factory para conseguir exportar qualquer dado em qualquer formato implementado.

+
+
+

O código fonte do projeto está disponível aqui (zip), mas tente primeiro implementar antes de ver o projeto.

+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/01-simple-factory/exportador-simple-factory-reflection/README.adoc b/criacionais/01-simple-factory/exportador-simple-factory-reflection/README.adoc deleted file mode 100755 index 9eab31799..000000000 --- a/criacionais/01-simple-factory/exportador-simple-factory-reflection/README.adoc +++ /dev/null @@ -1,11 +0,0 @@ -:source-highlighter: highlightjs - -= Exportação de lista de objetos em diferentes formatos (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/01-simple-factory/exportador-simple-factory-reflection[zip]) - -Esta versão do projeto apresentado link:../exportador-simple-factory[anteriormente] implementa -a exportação de dados de uma lista de qualquer tipo de objetos para formatos como HTML e Markdown (extensão .md). - -Tal versão utiliza o recurso de https://www.devmedia.com.br/conhecendo-java-reflection/29148[Reflection] da linguagem Java para descobrir automaticamente os atributos existentes nos objetos da lista a ser exportada. -Assim, tais atributos se transformam nas colunas da tabela gerada no formato escolhido. - -Esta é uma implementação mais flexível e realista, pois permite exportar qualquer tipo de lista. diff --git a/criacionais/01-simple-factory/exportador-simple-factory-reflection/README.html b/criacionais/01-simple-factory/exportador-simple-factory-reflection/README.html new file mode 100644 index 000000000..9e750cb18 --- /dev/null +++ b/criacionais/01-simple-factory/exportador-simple-factory-reflection/README.html @@ -0,0 +1,468 @@ + + + + + + + +Exportação de lista de objetos em diferentes formatos (zip) + + + + + + +
+
+

Esta versão do projeto apresentado anteriormente implementa +a exportação de dados de uma lista de qualquer tipo de objetos para formatos como HTML e Markdown (extensão .md).

+
+
+

Tal versão utiliza o recurso de Reflection da linguagem Java para descobrir automaticamente os atributos existentes nos objetos da lista a ser exportada. +Assim, tais atributos se transformam nas colunas da tabela gerada no formato escolhido.

+
+
+

Esta é uma implementação mais flexível e realista, pois permite exportar qualquer tipo de lista.

+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/01-simple-factory/exportador-simple-factory-reflection/index.html b/criacionais/01-simple-factory/exportador-simple-factory-reflection/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/01-simple-factory/exportador-simple-factory-reflection/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/01-simple-factory/exportador-simple-factory/README.adoc b/criacionais/01-simple-factory/exportador-simple-factory/README.adoc deleted file mode 100755 index 9c4934968..000000000 --- a/criacionais/01-simple-factory/exportador-simple-factory/README.adoc +++ /dev/null @@ -1,12 +0,0 @@ -:imagesdir: ../../../images/patterns/criacionais -:source-highlighter: highlightjs - -= Exportação de lista de produtos em diferentes formatos (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/01-simple-factory/exportador-simple-factory[zip]) - -Este é um projeto que implementa a exportação de dados de uma lista de produtos para formatos como HTML e Markdown (extensão .md). -Ela é uma versão introdutória bastante limitada, pois só trabalha com lista de produtos. -Para exportar uma lista de outro tipo de objeto, seria necessário implementar novas classes, -não sendo uma solução viável. - -.Diagrama de classes para implementação do exportador de lista de produtos para HTML e Markdown. -image::exportador-simple-factory.png[] diff --git a/criacionais/01-simple-factory/exportador-simple-factory/README.html b/criacionais/01-simple-factory/exportador-simple-factory/README.html new file mode 100644 index 000000000..91194f1ea --- /dev/null +++ b/criacionais/01-simple-factory/exportador-simple-factory/README.html @@ -0,0 +1,469 @@ + + + + + + + +Exportação de lista de produtos em diferentes formatos (zip) + + + + + + +
+
+

Este é um projeto que implementa a exportação de dados de uma lista de produtos para formatos como HTML e Markdown (extensão .md). +Ela é uma versão introdutória bastante limitada, pois só trabalha com lista de produtos. +Para exportar uma lista de outro tipo de objeto, seria necessário implementar novas classes, +não sendo uma solução viável.

+
+
+
+exportador simple factory +
+
Figure 1. Diagrama de classes para implementação do exportador de lista de produtos para HTML e Markdown.
+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/01-simple-factory/exportador-simple-factory/index.html b/criacionais/01-simple-factory/exportador-simple-factory/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/01-simple-factory/exportador-simple-factory/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/01-simple-factory/index.html b/criacionais/01-simple-factory/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/01-simple-factory/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/01-simple-factory/modelagem/README.adoc b/criacionais/01-simple-factory/modelagem/README.adoc deleted file mode 100755 index b3f9afdee..000000000 --- a/criacionais/01-simple-factory/modelagem/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ -= Modelagem do Padrão Simple Factory (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/01-simple-factory/modelagem/[zip]) - -Apresenta um código de exemplo da modelagem do padrão Simple Factory. -Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. -Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos. diff --git a/criacionais/01-simple-factory/modelagem/README.html b/criacionais/01-simple-factory/modelagem/README.html new file mode 100644 index 000000000..4da479d58 --- /dev/null +++ b/criacionais/01-simple-factory/modelagem/README.html @@ -0,0 +1,454 @@ + + + + + + + +Modelagem do Padrão Simple Factory (zip) + + + + + +
+
+

Apresenta um código de exemplo da modelagem do padrão Simple Factory. +Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. +Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos.

+
+
+ + + \ No newline at end of file diff --git a/criacionais/01-simple-factory/modelagem/index.html b/criacionais/01-simple-factory/modelagem/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/01-simple-factory/modelagem/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/README.adoc b/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/README.adoc deleted file mode 100755 index 1d4fc4c56..000000000 --- a/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/README.adoc +++ /dev/null @@ -1,19 +0,0 @@ -:source-highlighter: highlightjs - -= Leitura Dinâmica de Retorno de Boletos Bancários usando Template Method e Simple Factory (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic[zip]) - -Esta versão do projeto implementa a leitura de retorno de boletos com o padrão -Strategy e Template Method, evitando a duplicação de código existente na versão anterior utilizando apenas -o padrão Strategy. - -Por estar utilizando os dois padrões em conjunto, note que -a estrutura das classes não reflete exatamente os diagramas apresentados -na link:../[pasta anterior]. - -Esta é uma versão alternativa do projeto link:retorno-boleto-simple-factory[retorno-boleto-simple-factory] -que não utiliza programação funcional e evita o uso de blocos de `if` para selecionar qual classe instanciar. -Ela utiliza carregamento dinâmico de classes utilizando o método `Class.forName()`, -descobrindo automaticamente qual o nome da classe que deve ler um arquivo de um -determinado banco. Se a classe existir, ela será carregada. -Com esta implementação a Simple Factory é totalmente aderente ao -Open/Closed Principle (OCP). diff --git a/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/README.html b/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/README.html new file mode 100644 index 000000000..664088488 --- /dev/null +++ b/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/README.html @@ -0,0 +1,476 @@ + + + + + + + +Leitura Dinâmica de Retorno de Boletos Bancários usando Template Method e Simple Factory (zip) + + + + + + +
+
+

Esta versão do projeto implementa a leitura de retorno de boletos com o padrão +Strategy e Template Method, evitando a duplicação de código existente na versão anterior utilizando apenas +o padrão Strategy.

+
+
+

Por estar utilizando os dois padrões em conjunto, note que +a estrutura das classes não reflete exatamente os diagramas apresentados +na pasta anterior.

+
+
+

Esta é uma versão alternativa do projeto retorno-boleto-simple-factory +que não utiliza programação funcional e evita o uso de blocos de if para selecionar qual classe instanciar. +Ela utiliza carregamento dinâmico de classes utilizando o método Class.forName(), +descobrindo automaticamente qual o nome da classe que deve ler um arquivo de um +determinado banco. Se a classe existir, ela será carregada. +Com esta implementação a Simple Factory é totalmente aderente ao +Open/Closed Principle (OCP).

+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/index.html b/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/01-simple-factory/retorno-boleto-simple-factory-dynamic/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/01-simple-factory/retorno-boleto-simple-factory/README.adoc b/criacionais/01-simple-factory/retorno-boleto-simple-factory/README.adoc deleted file mode 100755 index d7736b539..000000000 --- a/criacionais/01-simple-factory/retorno-boleto-simple-factory/README.adoc +++ /dev/null @@ -1,12 +0,0 @@ -:source-highlighter: highlightjs - -= Leitura de Retorno de Boletos Bancários usando Simple Factory e uma implementação funcional do Template Method (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/01-simple-factory/retorno-boleto-simple-factory[zip]) - -Esta versão do projeto implementa a leitura de retorno de boletos com o padrão -Strategy e Template Method, evitando a duplicação de código existente na versão anterior utilizando apenas -o padrão Strategy. No entanto, o projeto utiliza programação funcional para tornar -as implementações mais simples. - -Por estar utilizando os dois padrões em conjunto, note que -a estrutura das classes não reflete exatamente os diagramas apresentados -na link:../[pasta anterior]. diff --git a/criacionais/01-simple-factory/retorno-boleto-simple-factory/README.html b/criacionais/01-simple-factory/retorno-boleto-simple-factory/README.html new file mode 100644 index 000000000..d9c165504 --- /dev/null +++ b/criacionais/01-simple-factory/retorno-boleto-simple-factory/README.html @@ -0,0 +1,468 @@ + + + + + + + +Leitura de Retorno de Boletos Bancários usando Simple Factory e uma implementação funcional do Template Method (zip) + + + + + + +
+
+

Esta versão do projeto implementa a leitura de retorno de boletos com o padrão +Strategy e Template Method, evitando a duplicação de código existente na versão anterior utilizando apenas +o padrão Strategy. No entanto, o projeto utiliza programação funcional para tornar +as implementações mais simples.

+
+
+

Por estar utilizando os dois padrões em conjunto, note que +a estrutura das classes não reflete exatamente os diagramas apresentados +na pasta anterior.

+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/01-simple-factory/retorno-boleto-simple-factory/index.html b/criacionais/01-simple-factory/retorno-boleto-simple-factory/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/01-simple-factory/retorno-boleto-simple-factory/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/01-simple-factory/slides.adoc b/criacionais/01-simple-factory/slides.adoc deleted file mode 100755 index f860f0cca..000000000 --- a/criacionais/01-simple-factory/slides.adoc +++ /dev/null @@ -1,188 +0,0 @@ -//:revealjsdir: https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.8.0/ -:revealjsdir: https://unpkg.com/reveal.js@4.3.1 -:revealjs_slideNumber: true -:source-highlighter: highlightjs -:icons: font -:allow-uri-read: -:imagesdir: ../../images -:stylesheet: ../../adoc-golo.css -:customcss: ../../slides-base.css -:numbered: -:toc: left -:toc-title: Sumário -:toclevels: 5 - -ifdef::env-github[] -//Exibe ícones para os blocos como NOTE e IMPORTANT no GitHub - -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -:chapter-label: -:listing-caption: Listagem -:figure-caption: Figura - -//Transição para todos os slides // none/fade/slide/convex/concave/zoom -//:revealjs_transition: 'zoom' - -//https://github.com/hakimel/reveal.js#theming -:revealjs_theme: league - -= Padrão Simple Factory - -image:patterns/simple-factory-logo.png[size=contain, title="Imagem pixabay.com"] - -Prof. Manoel Campos - -[transition=zoom] -== Categoria - -Padrão de projeto criacional image:ice-cream-sandwich-machine.gif[title=https://twistedsifter.com, link=https://twistedsifter.com/category/angifs/page/6/] - -[transition=fade] -== Definição - -[%step] -- Simple Factory permite encapsular a criação de objetos em uma classe que representa uma fábrica. -- Ela não é de fato um padrão de projeto, podendo ser definida como um modelo para a criação de objetos. - -[transition=fade] -== ! - -"Menção honroza" ao Simple Factory image:honor.png[text=http://www.free-icons-download.net, link=http://www.free-icons-download.net/medal-of-honor-icons-30279/, width="60px"] - -image::ucpp.jpg[size=contain] - -[transition=zoom] -== Aplicabilidade - -[%step] -Operador `new` utilizado para instanciar objetos em muitas linguagens. - -image:patterns/criacionais/escultor.gif[title=https://www.pnggif.com, link=https://www.pnggif.com/animation/work-gif-270105] - -[transition=fade] -== Motivação - -Declaração e instanciação -[source,java] ----- -TipoAbstrato variavel = new TipoConcreto() ----- - -[transition=fade, background-opacity=0.4] -== Motivação - -E se existir uma lógica que define qual tipo concreto será utilizado em um determinado momento? - -image::woman-thinking.jpg[background, title=https://www.versterkdeopvoeding.nl/category/algemeen/] - -[transition=zoom] -== Aplicabilidade - -[%step] -- Simple Factory para encapsular a criação destes objetos. -- Evitamos duplicar esta lógica em vários locais do projeto. - -[transition=fade, background-opacity=0.3] -== Aplicabilidade - -Tal lógica é normalmente representada por um bloco de `if()` que define as condições para a criação dos objetos. - -image::hadouken_if.jpg[background, title=https://www.reddit.com, link=https://www.reddit.com/r/ProgrammerHumor/comments/27yykv/indent_hadouken/] - -[transition=fade, background-opacity=0.2] -== Aplicabilidade - -[%step] -- Considere que temos várias subclasses que podem ser instanciadas. -- Ao usar `new`, substituir estas instâncias por uma outra sub-classe pode ser trabalhoso. -- Simple Factory: a criação de objetos de um super-tipo fica encapsulada e centralizada. - -image::subclass-superclass.png[background, size=contain] - -== ! - -.Modelagem -image::patterns/criacionais/simple-factory.png[] - -[transition=zoom, background-opacity=0.4] -== Princípios utilizados - -[%step] -- https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)] -- https://tuhrig.de/programming-to-an-interface/[Programar para uma "interface" não uma implementação (GoF)]: `TipoAbstrato variavel;` - -image::recommendations.jpg[background, size=contain, text=https://www.smart-energy.com, link=https://www.smart-energy.com/industry-sectors/smart-energy/five-key-recommendations-for-the-sustainable-energy-sector-growth-in-mena/] - -[transition=fade, background-opacity=0.4] -== Princípios utilizados - -[%step] -- https://en.wikipedia.org/wiki/Dependency_inversion_principle[Dependency Inversion Principle (DIP)] -- cliente da Factory não depende mais de tipos concretos - -image::recommendations.jpg[background, size=contain, text=https://www.smart-energy.com, link=https://www.smart-energy.com/industry-sectors/smart-energy/five-key-recommendations-for-the-sustainable-energy-sector-growth-in-mena/] - -[transition=fade] -== ! - -.Dependências com a NÃO utilização da Simple Factory -image::patterns/criacionais/no-simple-factory.png[width="50%"] - -[transition=fade] -== ! - -.Usando a Simple Factory (classe SimpleFactory omitida) -image::patterns/criacionais/simple-factory-dip.png[width="50%"] - -== Comparando as duas modelagens - -!=== -| Sem a factory image:patterns/criacionais/no-simple-factory.png[] | Com a factory (classe SimpleFactory omitida) image:patterns/criacionais/simple-factory-dip.png[] -!=== - -== Onde o padrão é usado no JDK - -A partir do JDK 9, as classes Collection introduziram os chamados -"Factory Methods" Apesar do nome ser o de outro padrão que veremos -à frente, tal padrão não é implementado aqui. O que temos é simplesmente -uma Simple Fatory. - -== JCF no JDK 9+ -[source, java] ----- -List listaNomes = List.of("Minha", "Lista", "de", "Strings"); ----- - -== JCF no JDK 9+ -[source, java] ----- -List listaPares = List.of(2, 4, 6, 8, 10); ----- - -== JCF no JDK 9+ - -[source, java] ----- -Map mapaHabitantesCidade = - Map.of("Palmas", 217000, "Gurupi", 84000); ----- - -== Falando de JDK, pula pro JDK 10 - -== ! -[source, java] ----- -var listaNomes = List.of("Minha", "Lista", "de", "Strings"); -var listaPares = List.of(2, 4, 6); -var mapaHabitantesCidade = Map.of("Palmas", 217000, "Gurupi", 84000); ----- - -== ! - -Faça você mesmo: Implemente uma Simple Factory no Projeto do Retorno Boleto diff --git a/criacionais/01-simple-factory/slides.html b/criacionais/01-simple-factory/slides.html new file mode 100644 index 000000000..b91a34263 --- /dev/null +++ b/criacionais/01-simple-factory/slides.html @@ -0,0 +1,1000 @@ + + + + + + + +Padrão Simple Factory + + + + + + +
+
+
+
+

simple factory logo

+
+
+

Prof. Manoel Campos

+
+
+
+
+

1. Categoria

+
+
+

Padrão de projeto criacional ice cream sandwich machine

+
+
+
+
+

2. Definição

+
+
+
    +
  • +

    Simple Factory permite encapsular a criação de objetos em uma classe que representa uma fábrica.

    +
  • +
  • +

    Ela não é de fato um padrão de projeto, podendo ser definida como um modelo para a criação de objetos.

    +
  • +
+
+
+
+
+

3. !

+
+
+

"Menção honroza" ao Simple Factory honor

+
+
+
+ucpp +
+
+
+
+
+

4. Aplicabilidade

+
+
+

Operador new utilizado para instanciar objetos em muitas linguagens.

+
+
+

escultor

+
+
+
+
+

5. Motivação

+
+
+

Declaração e instanciação

+
+
+
+
TipoAbstrato variavel = new TipoConcreto()
+
+
+
+
+
+

6. Motivação

+
+
+

E se existir uma lógica que define qual tipo concreto será utilizado em um determinado momento?

+
+ +
+
+
+

7. Aplicabilidade

+
+
+
    +
  • +

    Simple Factory para encapsular a criação destes objetos.

    +
  • +
  • +

    Evitamos duplicar esta lógica em vários locais do projeto.

    +
  • +
+
+
+
+
+

8. Aplicabilidade

+
+
+

Tal lógica é normalmente representada por um bloco de if() que define as condições para a criação dos objetos.

+
+
+
+background +
+ +
+
+
+
+

9. Aplicabilidade

+
+
+
    +
  • +

    Considere que temos várias subclasses que podem ser instanciadas.

    +
  • +
  • +

    Ao usar new, substituir estas instâncias por uma outra sub-classe pode ser trabalhoso.

    +
  • +
  • +

    Simple Factory: a criação de objetos de um super-tipo fica encapsulada e centralizada.

    +
  • +
+
+
+
+background +
+
+
+
+
+

10. !

+
+
+
+simple factory +
+
Figura 3. Modelagem
+
+
+
+
+

11. Princípios utilizados

+ +
+
+

12. Princípios utilizados

+
+
+ +
+
+
+background +
+
+
+
+
+

13. !

+
+
+
+no simple factory +
+
Figura 4. Dependências com a NÃO utilização da Simple Factory
+
+
+
+
+

14. !

+
+
+
+simple factory dip +
+
Figura 5. Usando a Simple Factory (classe SimpleFactory omitida)
+
+
+
+
+

15. Comparando as duas modelagens

+
+ ++++ + + + + + + +

Sem a factory no simple factory

Com a factory (classe SimpleFactory omitida) simple factory dip

+
+
+
+

16. Onde o padrão é usado no JDK

+
+
+

A partir do JDK 9, as classes Collection introduziram os chamados +"Factory Methods" Apesar do nome ser o de outro padrão que veremos +à frente, tal padrão não é implementado aqui. O que temos é simplesmente +uma Simple Fatory.

+
+
+
+
+

17. JCF no JDK 9+

+
+
+
+
List<String> listaNomes = List.of("Minha", "Lista", "de", "Strings");
+
+
+
+
+
+

18. JCF no JDK 9+

+
+
+
+
List<Integer> listaPares = List.of(2, 4, 6, 8, 10);
+
+
+
+
+
+

19. JCF no JDK 9+

+
+
+
+
Map<String, Integer> mapaHabitantesCidade =
+                        Map.of("Palmas", 217000, "Gurupi", 84000);
+
+
+
+
+
+

20. Falando de JDK, pula pro JDK 10

+
+ +
+
+
+

21. !

+
+
+
+
var listaNomes = List.of("Minha", "Lista", "de", "Strings");
+var listaPares = List.of(2, 4, 6);
+var mapaHabitantesCidade = Map.of("Palmas", 217000, "Gurupi", 84000);
+
+
+
+
+
+

22. !

+
+
+

Faça você mesmo: Implemente uma Simple Factory no Projeto do Retorno Boleto

+
+
+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/02-factory-method/README.adoc b/criacionais/02-factory-method/README.adoc deleted file mode 100644 index 54991a6c1..000000000 --- a/criacionais/02-factory-method/README.adoc +++ /dev/null @@ -1,124 +0,0 @@ -:imagesdir: ../../images/patterns/criacionais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Criacionais - -IMPORTANT: https://www.youtube.com/watch?v=6I5rGX3k_J4&list=PLyo0RUAM69UtO8Jjq71qgvRxcI2pTrB2m&index=8&t=0s[Vídeo-aula sobre o padrão.] - -== Factory Method (Método Fábrica) - -=== Definição - -// tag::definicao[] -📘"Fornece uma interface para criar um objeto, mas permite às subclasses decidirem qual tipo de objeto instanciar." [UCPP] -// end::definicao[] - -=== Aplicabilidade - -Podemos utilizar o padrão quando: - -// tag::aplicabilidade1[] -- uma classe precisa utilizar um tipo de objeto, mas ela não tem como decidir qual tipo concreto utilizar, pois tal lógica é definida por subclasses; -- cada subclasse tem uma lógica diferente para a criação dos objetos (juntar estas lógicas na superclasse tornaria o código extenso e confuso); -// end::aplicabilidade1[] -// tag::aplicabilidade2[] -- novas subclasses puderem ser introduzidas a qualquer momento com diferentes lógicas; -- você não conhece todos os tipos concretos de objetos que podem ser criados; -- é necessário criar objetos por meio de **composição**, cada objeto instanciado é um **todo** composto por diferentes **partes**, tais partes devem ser escolhidas de acordo com o todo. -// end::aplicabilidade2[] - -=== Modelagem - -.Modelagem do Factory Method -image::factory-method.png[] - -`TipoAbstrato` é uma interface ou classe abstrata/super classe que representa o tipo dos objetos que a fábrica pode criar. -As classes `TipoConcreto1` até `TipoConcretoN` representam os tipos concretos que podem ser instanciados de fato pela fábrica. -`CriadorAbstrato` representa a implementação base da fábrica. Ela pode ter quaisquer métodos que forem necessários, -incluindo um método abstrato `newObject()` que deverá ser implementados pelos criadores concretos. - -A classe `CriadorAbstrato` normalmente terá um método que chamará o `newObject()` para usar o objeto criado. -Neste exemplo, tal método é o `useObject()`, mas em uma implementação real, o método deve ter um nome de acordo -com o problema sendo resolvido. - -Diferente da Simple Factory: - -- a lógica que define qual objeto será instanciado não é centralizada em uma classe, mas sim nas subclasses de `CriadorAbstrato`; -- logo, o método `newObject()` é abstrato, pois as subclasses de `CriadorAbstrato` é que o implementarão. -- tal método não deve ser estático se ele for usado por outros métodos da classe (como é o caso deste modelo); - -Cada subclasse de `CriadorAbstrato` é que definirá a lógica para a instanciação do objeto representado por `TipoAbstrato`. -Para a Simple Factory não existem subclasses. - -Um projeto de exemplo para o diagrama apresentado está disponível link:modelagem[aqui]. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão. - -=== Princípios utilizados - -==== Single-Responsitility Principle - -Com o https://en.wikipedia.org/wiki/Single-responsibility_principle[Single-Responsitility Principle (SRP)], a classe `CriadorAbstrato` de fato não cria os objetos, apenas define um método que as filhas devem implementar para isto. -Ela apenas usará os objetos criados. Cada subclasse terá a responsabilidade de criar tais objetos. - -==== Open-Closed Principle - -Com o https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)], separamos as partes que mudam, i.e. a lógica de criação de objetos, de dentro da classe que utiliza tais objetos. Isto torna a classe que utiliza a factory "aberta para extensão e fechada para modificação". - -==== Programar para uma "interface" não uma implementação - -https://tuhrig.de/programming-to-an-interface/[Programar para uma "interface" não uma implementação] (GoF) indica que devemos declar variáveis com tipos abstratos (`TipoAbstrato`) e usar tipos concretos apenas na instanciação (`SubTipo1` ... `SubTipoN`). - -==== Dependency Inversion Principle (DIP) - -Ao aplicar o https://en.wikipedia.org/wiki/Dependency_inversion_principle[Dependency Inversion Principle (DIP)], a classe `CriadorAbstrato` não depende de tipos concretos, mas sim de tipos abstratos (interfaces ou classes abstratas). -Ela não precisa saber quais são os tipos concretos existentes. - -=== Remodelando o projeto Exportador Produto com a Simple Factory - -Antes de implementarmos o padrão Factory Method, precisamos -voltar ao projeto anterior, para fazer algumas alterações -considerando um novo cenário. - -Os detalhes são fornecidos no projeto link:exportador-problematico[exportador-problematico]. - -=== Exemplos - -Podemos utilizar o Factory Method para encapsular a instanciação de colunas de uma tabela em formato específico, -baseado no projeto link:../simple-factory/exportador-simple-factory-reflection[exportador-simple-factory-reflection]. -Implemente o projeto seguindo a modelagem abaixo: - -.Factory Method para a instanciação de colunas de uma tabela em formato específico -image::factory-method-exportador.png[] - -O código fonte do projeto está disponível link:exportador-factory-method-reflection[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/factory-method/exportador-factory-method-reflection[zip]). - -=== Detalhes de Implementação - -xxxxxxxxxxxx - -== Problemas da **NÃO** utilização do padrão - -Veja o projeto link:exportador-problematico[exportador-problematico] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/factory-method/exportador-problematico[zip]). -Ele é uma implementação do exportador de dados sem utilizar o padrão Factory Method, -seguindo a modelagem do diagrama abaixo: - -.Exportador de dados que NÃO usa o padrão Factory Method -image::no-factory-method-exportador-produtos.png[] - -== Padrões Relacionados - -Padrões que possuem similaridades ou podem ser usados em conjunto: - -- link:../simple-factory[Simple Factory] -- link:../../comportamentais/template-method[Template Method] diff --git a/criacionais/02-factory-method/README.html b/criacionais/02-factory-method/README.html new file mode 100644 index 000000000..01bfe717b --- /dev/null +++ b/criacionais/02-factory-method/README.html @@ -0,0 +1,650 @@ + + + + + + + +Padrões de Projetos Criacionais + + + + + + + +
+
+
+
+ + + + + +
+ + +Vídeo-aula sobre o padrão. +
+
+
+
+
+

1. Factory Method (Método Fábrica)

+
+
+

1.1. Definição

+
+

📘"Fornece uma interface para criar um objeto, mas permite às subclasses decidirem qual tipo de objeto instanciar." [UCPP]

+
+
+
+

1.2. Aplicabilidade

+
+

Podemos utilizar o padrão quando:

+
+
+
    +
  • +

    uma classe precisa utilizar um tipo de objeto, mas ela não tem como decidir qual tipo concreto utilizar, pois tal lógica é definida por subclasses;

    +
  • +
  • +

    cada subclasse tem uma lógica diferente para a criação dos objetos (juntar estas lógicas na superclasse tornaria o código extenso e confuso);

    +
  • +
  • +

    novas subclasses puderem ser introduzidas a qualquer momento com diferentes lógicas;

    +
  • +
  • +

    você não conhece todos os tipos concretos de objetos que podem ser criados;

    +
  • +
  • +

    é necessário criar objetos por meio de composição, cada objeto instanciado é um todo composto por diferentes partes, tais partes devem ser escolhidas de acordo com o todo.

    +
  • +
+
+
+
+

1.3. Modelagem

+
+
+factory method +
+
Figure 1. Modelagem do Factory Method
+
+
+

TipoAbstrato é uma interface ou classe abstrata/super classe que representa o tipo dos objetos que a fábrica pode criar. +As classes TipoConcreto1 até TipoConcretoN representam os tipos concretos que podem ser instanciados de fato pela fábrica. +CriadorAbstrato representa a implementação base da fábrica. Ela pode ter quaisquer métodos que forem necessários, +incluindo um método abstrato newObject() que deverá ser implementados pelos criadores concretos.

+
+
+

A classe CriadorAbstrato normalmente terá um método que chamará o newObject() para usar o objeto criado. +Neste exemplo, tal método é o useObject(), mas em uma implementação real, o método deve ter um nome de acordo +com o problema sendo resolvido.

+
+
+

Diferente da Simple Factory:

+
+
+
    +
  • +

    a lógica que define qual objeto será instanciado não é centralizada em uma classe, mas sim nas subclasses de CriadorAbstrato;

    +
  • +
  • +

    logo, o método newObject() é abstrato, pois as subclasses de CriadorAbstrato é que o implementarão.

    +
  • +
  • +

    tal método não deve ser estático se ele for usado por outros métodos da classe (como é o caso deste modelo);

    +
  • +
+
+
+

Cada subclasse de CriadorAbstrato é que definirá a lógica para a instanciação do objeto representado por TipoAbstrato. +Para a Simple Factory não existem subclasses.

+
+
+

Um projeto de exemplo para o diagrama apresentado está disponível aqui. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão.

+
+
+
+

1.4. Princípios utilizados

+
+

1.4.1. Single-Responsitility Principle

+
+

Com o Single-Responsitility Principle (SRP), a classe CriadorAbstrato de fato não cria os objetos, apenas define um método que as filhas devem implementar para isto. +Ela apenas usará os objetos criados. Cada subclasse terá a responsabilidade de criar tais objetos.

+
+
+
+

1.4.2. Open-Closed Principle

+
+

Com o Open/Closed Principle (OCP), separamos as partes que mudam, i.e. a lógica de criação de objetos, de dentro da classe que utiliza tais objetos. Isto torna a classe que utiliza a factory "aberta para extensão e fechada para modificação".

+
+
+
+

1.4.3. Programar para uma "interface" não uma implementação

+
+

Programar para uma "interface" não uma implementação (GoF) indica que devemos declar variáveis com tipos abstratos (TipoAbstrato) e usar tipos concretos apenas na instanciação (SubTipo1 …​ SubTipoN).

+
+
+
+

1.4.4. Dependency Inversion Principle (DIP)

+
+

Ao aplicar o Dependency Inversion Principle (DIP), a classe CriadorAbstrato não depende de tipos concretos, mas sim de tipos abstratos (interfaces ou classes abstratas). +Ela não precisa saber quais são os tipos concretos existentes.

+
+
+
+
+

1.5. Remodelando o projeto Exportador Produto com a Simple Factory

+
+

Antes de implementarmos o padrão Factory Method, precisamos +voltar ao projeto anterior, para fazer algumas alterações +considerando um novo cenário.

+
+
+

Os detalhes são fornecidos no projeto exportador-problematico.

+
+
+
+

1.6. Exemplos

+
+

Podemos utilizar o Factory Method para encapsular a instanciação de colunas de uma tabela em formato específico, +baseado no projeto exportador-simple-factory-reflection. +Implemente o projeto seguindo a modelagem abaixo:

+
+
+
+factory method exportador +
+
Figure 2. Factory Method para a instanciação de colunas de uma tabela em formato específico
+
+
+

O código fonte do projeto está disponível aqui (zip).

+
+
+
+

1.7. Detalhes de Implementação

+
+

xxxxxxxxxxxx

+
+
+
+
+
+

2. Problemas da NÃO utilização do padrão

+
+
+

Veja o projeto exportador-problematico (zip). +Ele é uma implementação do exportador de dados sem utilizar o padrão Factory Method, +seguindo a modelagem do diagrama abaixo:

+
+
+
+no factory method exportador produtos +
+
Figure 3. Exportador de dados que NÃO usa o padrão Factory Method
+
+
+
+
+

3. Padrões Relacionados

+
+
+

Padrões que possuem similaridades ou podem ser usados em conjunto:

+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/02-factory-method/exportador-factory-method-reflection/README.adoc b/criacionais/02-factory-method/exportador-factory-method-reflection/README.adoc deleted file mode 100755 index aa39c3023..000000000 --- a/criacionais/02-factory-method/exportador-factory-method-reflection/README.adoc +++ /dev/null @@ -1,12 +0,0 @@ -:source-highlighter: highlightjs - -= Exportação de lista de objetos em diferentes formatos (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/02-factory-method/exportador-factory-method-reflection[zip]) - -Esta é uma versão do projeto alink:../../simple-factory/exportador-simple-factory-reflection[anterior] que implementa -a exportação de dados de uma lista genérica de objetos para formatos como HTML e Markdown (extensão .md). -O projeto utiliza o recurso de Reflection do Java para descobrir automaticamente quais são os campos -dos objetos da lista que deve ser exportada. - -É aplicado o padrão link:../[Factory Method] para deixar as subclasses de `AbstractExportadorLista` -decidirem qual classe será instanciada quando decidirmos criar mais colunas para uma tabela em um formato -específico. diff --git a/criacionais/02-factory-method/exportador-factory-method-reflection/README.html b/criacionais/02-factory-method/exportador-factory-method-reflection/README.html new file mode 100644 index 000000000..7c86e6d7d --- /dev/null +++ b/criacionais/02-factory-method/exportador-factory-method-reflection/README.html @@ -0,0 +1,468 @@ + + + + + + + +Exportação de lista de objetos em diferentes formatos (zip) + + + + + + +
+
+

Esta é uma versão do projeto aanterior que implementa +a exportação de dados de uma lista genérica de objetos para formatos como HTML e Markdown (extensão .md). +O projeto utiliza o recurso de Reflection do Java para descobrir automaticamente quais são os campos +dos objetos da lista que deve ser exportada.

+
+
+

É aplicado o padrão Factory Method para deixar as subclasses de AbstractExportadorLista +decidirem qual classe será instanciada quando decidirmos criar mais colunas para uma tabela em um formato +específico.

+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/02-factory-method/exportador-factory-method-reflection/index.html b/criacionais/02-factory-method/exportador-factory-method-reflection/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/02-factory-method/exportador-factory-method-reflection/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/02-factory-method/exportador-problematico-generic/README.adoc b/criacionais/02-factory-method/exportador-problematico-generic/README.adoc deleted file mode 100755 index 5dd271c34..000000000 --- a/criacionais/02-factory-method/exportador-problematico-generic/README.adoc +++ /dev/null @@ -1,20 +0,0 @@ -:imagesdir: ../../../images/patterns/criacionais -:source-highlighter: highlightjs - -= Exportação Problemática de lista de objetos em diferentes formatos (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/02-factory-method/exportador-problematico[zip]) - -Esta é uma versão do projeto link:../exportador-factory-method-reflection[anterior] que implementa -a exportação de dados de uma lista genérica de objetos para formatos como HTML e Markdown (extensão .md). - -Aqui **NÃO** é aplicado o padrão link:../[Factory Method] e isso pode trazer problemas quando você -decidir adicionar novas colunas em uma tabela. Por exemplo, considerando que a classe `Usuario` -tem os atributos id, nome, cpf e cidade, podemos querer incluir uma coluna a mais na tabela gerada -a partir de uma lista destes objetos. Um exemplo seria a adição de uma coluna contendo apenas o sobrenome -do usuário. - -A classe `Principal` atualmente já está gerando tabelas de usuários com esta coluna "Sobrenome". -Altere o código da classe e tente descobrir qual problema pode acarretar. - - -.Exportador de dados que NÃO usa o padrão Factory Method -image::no-factory-method-exportador.png[] diff --git a/criacionais/02-factory-method/exportador-problematico-generic/README.html b/criacionais/02-factory-method/exportador-problematico-generic/README.html new file mode 100644 index 000000000..c225bf26c --- /dev/null +++ b/criacionais/02-factory-method/exportador-problematico-generic/README.html @@ -0,0 +1,478 @@ + + + + + + + +Exportação Problemática de lista de objetos em diferentes formatos (zip) + + + + + + +
+
+

Esta é uma versão do projeto anterior que implementa +a exportação de dados de uma lista genérica de objetos para formatos como HTML e Markdown (extensão .md).

+
+
+

Aqui NÃO é aplicado o padrão Factory Method e isso pode trazer problemas quando você +decidir adicionar novas colunas em uma tabela. Por exemplo, considerando que a classe Usuario +tem os atributos id, nome, cpf e cidade, podemos querer incluir uma coluna a mais na tabela gerada +a partir de uma lista destes objetos. Um exemplo seria a adição de uma coluna contendo apenas o sobrenome +do usuário.

+
+
+

A classe Principal atualmente já está gerando tabelas de usuários com esta coluna "Sobrenome". +Altere o código da classe e tente descobrir qual problema pode acarretar.

+
+
+
+no factory method exportador +
+
Figure 1. Exportador de dados que NÃO usa o padrão Factory Method
+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/02-factory-method/exportador-problematico-generic/index.html b/criacionais/02-factory-method/exportador-problematico-generic/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/02-factory-method/exportador-problematico-generic/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/02-factory-method/index.html b/criacionais/02-factory-method/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/02-factory-method/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/02-factory-method/modelagem/README.adoc b/criacionais/02-factory-method/modelagem/README.adoc deleted file mode 100755 index 5493ada1c..000000000 --- a/criacionais/02-factory-method/modelagem/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ -= Modelagem do Padrão Factory Method (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/02-factory-method/modelagem/[zip]) - -Apresenta um código de exemplo da modelagem do padrão Factory Method. -Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. -Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos. diff --git a/criacionais/02-factory-method/modelagem/README.html b/criacionais/02-factory-method/modelagem/README.html new file mode 100644 index 000000000..fa0711ece --- /dev/null +++ b/criacionais/02-factory-method/modelagem/README.html @@ -0,0 +1,454 @@ + + + + + + + +Modelagem do Padrão Factory Method (zip) + + + + + +
+
+

Apresenta um código de exemplo da modelagem do padrão Factory Method. +Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. +Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos.

+
+
+ + + \ No newline at end of file diff --git a/criacionais/02-factory-method/modelagem/index.html b/criacionais/02-factory-method/modelagem/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/02-factory-method/modelagem/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/02-factory-method/slides.adoc b/criacionais/02-factory-method/slides.adoc deleted file mode 100644 index f9408e4a3..000000000 --- a/criacionais/02-factory-method/slides.adoc +++ /dev/null @@ -1,145 +0,0 @@ -//:revealjsdir: https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.8.0/ -:revealjsdir: https://unpkg.com/reveal.js@4.3.1 -:revealjs_slideNumber: true -:source-highlighter: highlightjs -:icons: font -:allow-uri-read: -:imagesdir: ../../images -:stylesheet: ../../adoc-golo.css -:customcss: ../../slides-base.css -:numbered: -:toc: left -:toc-title: Sumário -:toclevels: 5 - -ifdef::env-github[] -//Exibe ícones para os blocos como NOTE e IMPORTANT no GitHub - -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -:chapter-label: -:listing-caption: Listagem -:figure-caption: Figura - -//Transição para todos os slides // none/fade/slide/convex/concave/zoom -//:revealjs_transition: 'zoom' - -//https://github.com/hakimel/reveal.js#theming -:revealjs_theme: league - -= Padrão de Projetos Factory Method - -Prof. Manoel Campos - -image::https://manoelcampos.com/padroes-projetos/images/biolink.png[] - -[transition=zoom] -== Categoria - -Padrão de projeto criacional image:ice-cream-sandwich-machine.gif[title=https://twistedsifter.com, link=https://twistedsifter.com/category/angifs/page/6/] - -[transition=fade] -== Definição - -include::README.adoc[tag=definicao] - -image:ucpp.jpg[size=contain] - -[transition=fade] -== Mas antes de entendermos o padrão 🤔... - -[transition=fade] -== ! - -image::patterns/criacionais/exportador-simple-factory.png[background, size=contain] - -[transition=fade] -== Vamos rever a aplicação em funcionamento - -- https://github.com/manoelcampos/padroes-projetos/blob/master/criacionais/simple-factory/exportador-simple-factory[O exportador de produtos] - -[transition=fade] -== Mas podemos ter problemas... - -[%step] -- Não segue o https://en.wikipedia.org/wiki/Single-responsibility_principle[Single-Responsitility Principle (SRP)] nem https://en.wikipedia.org/wiki/Interface_segregation_principle[Interface Segregation Principle (ISP)] 🤦 image:patterns/criacionais/interface-exportador-lista-produtos.png[] - -[transition=fade] -== Então como resolver? 🤯 - -[%step] -- Seguindo o ISP... -- e consequentemente o SRP -- A modelagem a seguir ainda **NÃO** implementa o padrão Factory Method - -[transition=fade] -== ! - -image::patterns/criacionais/no-factory-method-exportador.png[background, size=contain] - - -[transition=fade] -== Antes tínhamos um problema, agora criamos outro - -https://github.com/manoelcampos/padroes-projetos/tree/master/criacionais/factory-method/exportador-problematico[O exportador problemático 😭] - -[transition=zoom] -== Como resolver de vez? 😡 - -[transition=zoom] -== Utilizando o padrão Factory Method - -[transition=zoofadem] -== Aplicabilidade - -Quando: - -[%step] -include::README.adoc[tag=aplicabilidade1] - -[transition=fade] -== Aplicabilidade - -[%step] -include::README.adoc[tag=aplicabilidade2] - -[transition=zoom] -== Modelagem do Factory Method - -== ! - -image::patterns/criacionais/factory-method-exportador.png[background, size=contain] - -[transition=zoom, background-opacity=0.4] -== Princípios utilizados - -[%step] -- https://en.wikipedia.org/wiki/Single-responsibility_principle[Single-Responsitility Principle (SRP)] -- https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)] -- https://tuhrig.de/programming-to-an-interface/[Programar para uma "interface" não uma implementação (GoF)]: `TipoAbstrato variavel;` -- https://en.wikipedia.org/wiki/Dependency_inversion_principle[Dependency Inversion Principle (DIP)] - -image::recommendations.jpg[background, size=contain, text=https://www.smart-energy.com, link=https://www.smart-energy.com/industry-sectors/smart-energy/five-key-recommendations-for-the-sustainable-energy-sector-growth-in-mena/] - - -[transition=fade] -== ! - -.Dependências com a NÃO utilização de uma fábrica -image::patterns/criacionais/no-simple-factory.png[width="50%"] - -[transition=fade] -== ! - -.Usando uma fábrica -image::patterns/criacionais/simple-factory-dip.png[width="50%"] - -[transition=fade] -== Material e Projetos no GitHub - -https://git.io/JvpgW diff --git a/criacionais/02-factory-method/slides.html b/criacionais/02-factory-method/slides.html new file mode 100644 index 000000000..c50d385c5 --- /dev/null +++ b/criacionais/02-factory-method/slides.html @@ -0,0 +1,930 @@ + + + + + + + +Padrão de Projetos Factory Method + + + + + + +
+
+
+
+

Prof. Manoel Campos

+
+
+
+biolink +
+
+
+
+
+

1. Categoria

+
+
+

Padrão de projeto criacional ice cream sandwich machine

+
+
+
+
+

2. Definição

+
+
+

📘"Fornece uma interface para criar um objeto, mas permite às subclasses decidirem qual tipo de objeto instanciar." [UCPP]

+
+
+

ucpp

+
+
+
+
+

3. Mas antes de entendermos o padrão 🤔…​

+
+ +
+
+
+

4. !

+
+
+
+background +
+
+
+
+
+

5. Vamos rever a aplicação em funcionamento

+
+ +
+
+
+

6. Mas podemos ter problemas…​

+ +
+
+

7. Então como resolver? 🤯

+
+
+
    +
  • +

    Seguindo o ISP…​

    +
  • +
  • +

    e consequentemente o SRP

    +
  • +
  • +

    A modelagem a seguir ainda NÃO implementa o padrão Factory Method

    +
  • +
+
+
+
+
+

8. !

+
+
+
+background +
+
+
+
+
+

9. Antes tínhamos um problema, agora criamos outro

+ +
+
+

10. Como resolver de vez? 😡

+
+ +
+
+
+

11. Utilizando o padrão Factory Method

+
+ +
+
+
+

12. Aplicabilidade

+
+
+

Quando:

+
+
+
    +
  • +

    uma classe precisa utilizar um tipo de objeto, mas ela não tem como decidir qual tipo concreto utilizar, pois tal lógica é definida por subclasses;

    +
  • +
  • +

    cada subclasse tem uma lógica diferente para a criação dos objetos (juntar estas lógicas na superclasse tornaria o código extenso e confuso);

    +
  • +
+
+
+
+
+

13. Aplicabilidade

+
+
+
    +
  • +

    novas subclasses puderem ser introduzidas a qualquer momento com diferentes lógicas;

    +
  • +
  • +

    você não conhece todos os tipos concretos de objetos que podem ser criados;

    +
  • +
  • +

    é necessário criar objetos por meio de composição, cada objeto instanciado é um todo composto por diferentes partes, tais partes devem ser escolhidas de acordo com o todo.

    +
  • +
+
+
+
+
+

14. Modelagem do Factory Method

+
+ +
+
+
+

15. !

+
+
+
+background +
+
+
+
+ +
+

17. !

+
+
+
+no simple factory +
+
Figura 1. Dependências com a NÃO utilização de uma fábrica
+
+
+
+
+

18. !

+
+
+
+simple factory dip +
+
Figura 2. Usando uma fábrica
+
+
+
+
+

19. Material e Projetos no GitHub

+ +
+
+ + + + + \ No newline at end of file diff --git a/criacionais/03-singleton/README.adoc b/criacionais/03-singleton/README.adoc deleted file mode 100755 index b355ab674..000000000 --- a/criacionais/03-singleton/README.adoc +++ /dev/null @@ -1,115 +0,0 @@ -:imagesdir: ../../images/patterns/criacionais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Criacionais - -IMPORTANT: https://www.youtube.com/watch?v=VgDZsSMjmcU&list=PLyo0RUAM69UtO8Jjq71qgvRxcI2pTrB2m&index=9[Vídeo-aulas disponíveis aqui.] - -== Singleton - -image:lonely-2378396_1280.jpg[] - -=== Definição - -// tag::definicao[] -📘"Garante que uma classe tenha apenas uma instância e fornece um ponto global de acesso a ela." [UCPP] -// end::definicao[] - -=== Aplicabilidade - -Este é um padrão aplicado em casos excepcionais. - -// tag::aplicabilidade[] -- Quando precisa-se garantir que uma classe tenha uma única instância durante toda a execução da app; -- o objeto a ser criado possui dados únicos, compartilhados por todos os usuários da app; -- tal objeto exige muitos recursos (como memória) ou tem alto custo de instanciação; -- representa um dispositivo físico pro qual não faz sentido ter duas instância dentro da mesma app (como uma impresora). -// end::aplicabilidade[] - -=== Modelagem - -O padrão Singleton é representado por uma única classe como apresentado na figura a seguir. - -.Modelagem de uma classe que implementa o padrão Singleton -image::singleton.png[] - -O padrão Singleton é aplicado a uma classe por vez. -A classe Singleton será aquela que desejamos aplicar o padrão, logo, -normalmente é uma classe que já existe e que apenas queremos impedir -que sejam criadas múltiplas instâncias dela. -Assim, não teremos de fato uma classe chamada Singleton, -mas qualquer outro nome relacionado ao sistema que estamos desenvolvendo. - -O que faz com que a classe tenha apenas uma única instância, é armazenar tal instância -em um atributo estático e privado dentro da própria classe. Normalmente tal atributo é chamado -simplesmente de `instance`. O tipo dele será a própria classe onde ele está sendo declarado. -Se tivermos uma classe Singleton `ImpressoraFiscal`, ela terá um atributo `ImpressoraFiscal instance`. - -O método `getInstance()` deve retornar a instância armazenada no atributo `instance`, -logo, o tipo do retorno de tal método é a própria classe. No exemplo acima, será `ImpressoraFiscal`. -Ele é um método estático, uma vez que não devemos chamá-lo a partir de uma instância, mas sim a partir -da classe para que o método retorne a instância. - -Um detalhe importante é que o construtor deve ser privado. Isto é o principal para garantir que -uma única instância da classe será criada. -Para obter-se a instância única, devemos chamar o método `getInstance()`, já que não temos -como usar o construtor fora da classe. - -Um projeto de exemplo para o diagrama apresentado está disponível link:modelagem[aqui]. Este é uma exemplo prático que implementa o padrão Singleton para classe que simula a comunicação com uma impressora fiscal. - -=== Princípios utilizados - -Você poderia imaginar que o Singleton adere ao *Single*-Responsitility Principle (https://en.wikipedia.org/wiki/Single-responsibility_principle[SRP]), mas ele não garante que a classe terá uma única responsabilidade. Ele garante que a classe terá uma única instância. Um padrão pode propiciar o SRP, no entanto está mais nas mãos do desenvolvedor garantir um princípio que do padrão. - -Pelo fato do padrão ser tão simples que sua modelagem é uma única classe, ele não adere a nenhum princípio específico, mas apenas resolve um problema recorrente em desenvolvimento de software. - -=== Exemplos - -Um sistema pode ter um conjunto de configurações que o usuário pode alterar. -Considere que as configurações do sistema podem ser acessadas e alteradas em diversos locais. Neste caso, o mais apropriado é criar uma classe, chamada por exemplo de `Config`, que encapsula o gerenciamento de tais configurações. Se instanciarmos objetos da classe `Config` em diferentes locais e alterarmos as configurações, podemos ver os valores atualizados em determinados locais, enquanto aparecem desatualizados em outros. Isto pode trazer problemas para o sistema. - -Neste caso, podemos aplicar o padrão Singleton à classe `Config` para permitir que uma única instância dela seja criada para todo o sistema. -Mesmo que tenhamos diversas variáveis `Config` espalhadas pelo sistema, todas apontarão para um único objeto criado. -Assim, ao alterar uma configuração por meio de qualquer dessas variáveis, estaremos alterando o mesmo objeto. -Logo, teremos acesso aos mesmos dados, independetemente de qual variável utilizarmos. - -A figura abaixo apresenta a modelagem para a classe `Config` implementado o padrão Singleton. - -.Modelagem de uma classe que implementa o padrão Singleton para gerenciamento de configurações de um sistema -image::singleton-config.png[] - -O projeto link:config-singleton-spring[config-singleton-spring] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/singleton/config-singleton-spring[zip]) -fornece a estrutura de um backend com Spring que aplica o padrão Singleton para a classe Config e por padrão para qualquer -Spring Bean (objetos cujo ciclo de vida é controlado pelo Spring, como Controllers e Repositories). - -=== Detalhes de Implementação - -Para implementar o padrão Singleton, sempre tenha em mente os seguintes detalhes, -conforme pode ser observado na Figura 1 acima. - -- Deve-se explicitamente definir um construtor privado para a classe Singleton. Em java, se nenhum construtor for definido, o compilador automaticamente incluirá um construtor padrão público, que permitirá que a classe seja instanciada de qualquer lugar, quantas vezes desejarmos. Isto vai totalmente contra o padrão Singleton. -- A única instância a ser criada deve ser definida como um atributo privado e estático. Como ele é estático, só haverá uma única instância armazenada dentro da própria classe. Como é privado, não será possível alterar tal instância depois de o atributo ter sido inicializado. -- Deve existir um método `getInstance()` que deve verificar se um objeto já foi criado e apenas retorná-lo. Caso contrário, um novo objeto deve ser criado e armazenado no atributo estático comentado no item acima. - -== Padrões Relacionados - -Padrões que possuem similaridades ou podem ser usados em conjunto: - -- link:../factory-method[Factory Method] - -== Onde o padrão é usado no JDK - -- java.awt.Desktop -- java.lang.Runtime diff --git a/criacionais/03-singleton/README.html b/criacionais/03-singleton/README.html new file mode 100644 index 000000000..34c069c17 --- /dev/null +++ b/criacionais/03-singleton/README.html @@ -0,0 +1,637 @@ + + + + + + + +Padrões de Projetos Criacionais + + + + + + + +
+
+
+
+ + + + + +
+ + +Vídeo-aulas disponíveis aqui. +
+
+
+
+
+

1. Singleton

+
+
+

lonely 2378396 1280

+
+
+

1.1. Definição

+
+

📘"Garante que uma classe tenha apenas uma instância e fornece um ponto global de acesso a ela." [UCPP]

+
+
+
+

1.2. Aplicabilidade

+
+

Este é um padrão aplicado em casos excepcionais.

+
+
+
    +
  • +

    Quando precisa-se garantir que uma classe tenha uma única instância durante toda a execução da app;

    +
  • +
  • +

    o objeto a ser criado possui dados únicos, compartilhados por todos os usuários da app;

    +
  • +
  • +

    tal objeto exige muitos recursos (como memória) ou tem alto custo de instanciação;

    +
  • +
  • +

    representa um dispositivo físico pro qual não faz sentido ter duas instância dentro da mesma app (como uma impresora).

    +
  • +
+
+
+
+

1.3. Modelagem

+
+

O padrão Singleton é representado por uma única classe como apresentado na figura a seguir.

+
+
+
+singleton +
+
Figure 1. Modelagem de uma classe que implementa o padrão Singleton
+
+
+

O padrão Singleton é aplicado a uma classe por vez. +A classe Singleton será aquela que desejamos aplicar o padrão, logo, +normalmente é uma classe que já existe e que apenas queremos impedir +que sejam criadas múltiplas instâncias dela. +Assim, não teremos de fato uma classe chamada Singleton, +mas qualquer outro nome relacionado ao sistema que estamos desenvolvendo.

+
+
+

O que faz com que a classe tenha apenas uma única instância, é armazenar tal instância +em um atributo estático e privado dentro da própria classe. Normalmente tal atributo é chamado +simplesmente de instance. O tipo dele será a própria classe onde ele está sendo declarado. +Se tivermos uma classe Singleton ImpressoraFiscal, ela terá um atributo ImpressoraFiscal instance.

+
+
+

O método getInstance() deve retornar a instância armazenada no atributo instance, +logo, o tipo do retorno de tal método é a própria classe. No exemplo acima, será ImpressoraFiscal. +Ele é um método estático, uma vez que não devemos chamá-lo a partir de uma instância, mas sim a partir +da classe para que o método retorne a instância.

+
+
+

Um detalhe importante é que o construtor deve ser privado. Isto é o principal para garantir que +uma única instância da classe será criada. +Para obter-se a instância única, devemos chamar o método getInstance(), já que não temos +como usar o construtor fora da classe.

+
+
+

Um projeto de exemplo para o diagrama apresentado está disponível aqui. Este é uma exemplo prático que implementa o padrão Singleton para classe que simula a comunicação com uma impressora fiscal.

+
+
+
+

1.4. Princípios utilizados

+
+

Você poderia imaginar que o Singleton adere ao Single-Responsitility Principle (SRP), mas ele não garante que a classe terá uma única responsabilidade. Ele garante que a classe terá uma única instância. Um padrão pode propiciar o SRP, no entanto está mais nas mãos do desenvolvedor garantir um princípio que do padrão.

+
+
+

Pelo fato do padrão ser tão simples que sua modelagem é uma única classe, ele não adere a nenhum princípio específico, mas apenas resolve um problema recorrente em desenvolvimento de software.

+
+
+
+

1.5. Exemplos

+
+

Um sistema pode ter um conjunto de configurações que o usuário pode alterar. +Considere que as configurações do sistema podem ser acessadas e alteradas em diversos locais. Neste caso, o mais apropriado é criar uma classe, chamada por exemplo de Config, que encapsula o gerenciamento de tais configurações. Se instanciarmos objetos da classe Config em diferentes locais e alterarmos as configurações, podemos ver os valores atualizados em determinados locais, enquanto aparecem desatualizados em outros. Isto pode trazer problemas para o sistema.

+
+
+

Neste caso, podemos aplicar o padrão Singleton à classe Config para permitir que uma única instância dela seja criada para todo o sistema. +Mesmo que tenhamos diversas variáveis Config espalhadas pelo sistema, todas apontarão para um único objeto criado. +Assim, ao alterar uma configuração por meio de qualquer dessas variáveis, estaremos alterando o mesmo objeto. +Logo, teremos acesso aos mesmos dados, independetemente de qual variável utilizarmos.

+
+
+

A figura abaixo apresenta a modelagem para a classe Config implementado o padrão Singleton.

+
+
+
+singleton config +
+
Figure 2. Modelagem de uma classe que implementa o padrão Singleton para gerenciamento de configurações de um sistema
+
+
+

O projeto config-singleton-spring (zip) +fornece a estrutura de um backend com Spring que aplica o padrão Singleton para a classe Config e por padrão para qualquer +Spring Bean (objetos cujo ciclo de vida é controlado pelo Spring, como Controllers e Repositories).

+
+
+
+

1.6. Detalhes de Implementação

+
+

Para implementar o padrão Singleton, sempre tenha em mente os seguintes detalhes, +conforme pode ser observado na Figura 1 acima.

+
+
+
    +
  • +

    Deve-se explicitamente definir um construtor privado para a classe Singleton. Em java, se nenhum construtor for definido, o compilador automaticamente incluirá um construtor padrão público, que permitirá que a classe seja instanciada de qualquer lugar, quantas vezes desejarmos. Isto vai totalmente contra o padrão Singleton.

    +
  • +
  • +

    A única instância a ser criada deve ser definida como um atributo privado e estático. Como ele é estático, só haverá uma única instância armazenada dentro da própria classe. Como é privado, não será possível alterar tal instância depois de o atributo ter sido inicializado.

    +
  • +
  • +

    Deve existir um método getInstance() que deve verificar se um objeto já foi criado e apenas retorná-lo. Caso contrário, um novo objeto deve ser criado e armazenado no atributo estático comentado no item acima.

    +
  • +
+
+
+
+
+
+

2. Padrões Relacionados

+
+
+

Padrões que possuem similaridades ou podem ser usados em conjunto:

+
+
+ +
+
+
+
+

3. Onde o padrão é usado no JDK

+
+
+
    +
  • +

    java.awt.Desktop

    +
  • +
  • +

    java.lang.Runtime

    +
  • +
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/03-singleton/config-singleton-spring/README.adoc b/criacionais/03-singleton/config-singleton-spring/README.adoc deleted file mode 100644 index 337ab51cc..000000000 --- a/criacionais/03-singleton/config-singleton-spring/README.adoc +++ /dev/null @@ -1,3 +0,0 @@ -= Mostra como usar o padrão Singleton com Spring (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/03-singleton/config-singleton-spring[zip]) - -Projeto em Spring Boot que mostra como podemos usar objetos singleton de forma automática (usando apenas anotações) em um controller REST. diff --git a/criacionais/03-singleton/config-singleton-spring/README.html b/criacionais/03-singleton/config-singleton-spring/README.html new file mode 100644 index 000000000..c5b05effd --- /dev/null +++ b/criacionais/03-singleton/config-singleton-spring/README.html @@ -0,0 +1,452 @@ + + + + + + + +Mostra como usar o padrão Singleton com Spring (zip) + + + + + +
+
+

Projeto em Spring Boot que mostra como podemos usar objetos singleton de forma automática (usando apenas anotações) em um controller REST.

+
+
+ + + \ No newline at end of file diff --git a/criacionais/03-singleton/config-singleton-spring/index.html b/criacionais/03-singleton/config-singleton-spring/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/03-singleton/config-singleton-spring/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/03-singleton/index.html b/criacionais/03-singleton/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/03-singleton/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/03-singleton/modelagem/README.adoc b/criacionais/03-singleton/modelagem/README.adoc deleted file mode 100755 index 39992f637..000000000 --- a/criacionais/03-singleton/modelagem/README.adoc +++ /dev/null @@ -1,3 +0,0 @@ -= Modelagem do Padrão Singleton (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/03-singleton/modelagem/[zip]) - -Apresenta um projeto de exemplo da modelagem do padrão Singleton. diff --git a/criacionais/03-singleton/modelagem/README.html b/criacionais/03-singleton/modelagem/README.html new file mode 100644 index 000000000..fcae281cf --- /dev/null +++ b/criacionais/03-singleton/modelagem/README.html @@ -0,0 +1,452 @@ + + + + + + + +Modelagem do Padrão Singleton (zip) + + + + + +
+
+

Apresenta um projeto de exemplo da modelagem do padrão Singleton.

+
+
+ + + \ No newline at end of file diff --git a/criacionais/03-singleton/modelagem/index.html b/criacionais/03-singleton/modelagem/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/03-singleton/modelagem/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/03-singleton/slides.adoc b/criacionais/03-singleton/slides.adoc deleted file mode 100755 index c45aa4ae2..000000000 --- a/criacionais/03-singleton/slides.adoc +++ /dev/null @@ -1,117 +0,0 @@ -//:revealjsdir: https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.8.0/ -:revealjsdir: https://unpkg.com/reveal.js@4.3.1 -:revealjs_slideNumber: true -:source-highlighter: highlightjs -:icons: font -:allow-uri-read: -:imagesdir: ../../images -:stylesheet: ../../adoc-golo.css -:customcss: ../../slides-base.css -:numbered: -:toc: left -:toc-title: Sumário -:toclevels: 5 - -ifdef::env-github[] -//Exibe ícones para os blocos como NOTE e IMPORTANT no GitHub - -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -:chapter-label: -:listing-caption: Listagem -:figure-caption: Figura - -//Transição para todos os slides // none/fade/slide/convex/concave/zoom -//:revealjs_transition: 'zoom' - -//https://github.com/hakimel/reveal.js#theming -:revealjs_theme: league - -= Padrão de Projeto Singleton 💁🏼‍♀️ - -Prof. Manoel Campos - -image::https://manoelcampos.com/padroes-projetos/images/biolink.png[] - - -[transition=zoom] -== Categoria - -Padrão de projeto criacional image:ice-cream-sandwich-machine.gif[title=https://twistedsifter.com, link=https://twistedsifter.com/category/angifs/page/6/] - -[transition=fade] -== Definição - -include::README.adoc[tag=definicao] - -image:ucpp.jpg[size=contain] - -[transition=zoofadem] -== Aplicabilidade - -[%step] -include::README.adoc[tag=aplicabilidade] - -[transition=zoom] -== Modelagem do Singleton - -image:patterns/criacionais/singleton.png[] - -== ! - -image:patterns/criacionais/singleton.png[] - -[%step] -- Aplicado a uma classe por vez. -- A classe Singleton será a que aplicarmos o padrão. -- Armazena instância única em um atributo estático e privado: `instance`. - -== ! - -image:patterns/criacionais/singleton.png[] - -[%step] -- O atributo tem o tipo da própria classe. -- `getInstance()`: estático, retorna a instância armazenada no atributo `instance` -- Construtor privado. - -[transition=zoom, background-opacity=0.4] -== Princípios utilizados - -[%step] -- *Single*-Responsitility Principle (https://en.wikipedia.org/wiki/Single-responsibility_principle[SRP])? - -image::recommendations.jpg[background, size=contain, text=https://www.smart-energy.com, link=https://www.smart-energy.com/industry-sectors/smart-energy/five-key-recommendations-for-the-sustainable-energy-sector-growth-in-mena/] - -[transition=fade] -== Exemplos de uso do Singleton - -[%step] -- Classe para impressora fiscal em aplicação de PDV (Ponto de Venda). -- Arquivo de configuração a ser utilizado por todo o sistema. - -[transition=fade] -== Exemplos de uso do Singleton - -[%step] -- Hibernate `SessionFactory`: -- pesado -- carrega as configurações (parse de XML) de acesso ao BD -- cria sessões (conexões BD) -- https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html#configuration-hibernatejdbc[inicializa o Connection Pool] - -[transition=fade] -== Exemplos de uso do Singleton - -[quote, Minter and Linwood 2006] -https://books.google.com.br/books?id=0d12xElRjysC&printsec=frontcover["The SessionFactory is a heavyweight object, and there would normally be a single instance per application."] - -[transition=fade] -== Material e Projetos no GitHub - -https://github.com/manoelcampos/padroes-projetos/tree/master/criacionais/singleton diff --git a/criacionais/03-singleton/slides.html b/criacionais/03-singleton/slides.html new file mode 100644 index 000000000..29d6bf62f --- /dev/null +++ b/criacionais/03-singleton/slides.html @@ -0,0 +1,874 @@ + + + + + + + +Padrão de Projeto Singleton 💁🏼‍♀️ + + + + + + +
+
+
+
+

Prof. Manoel Campos

+
+
+
+biolink +
+
+
+
+
+

1. Categoria

+
+
+

Padrão de projeto criacional ice cream sandwich machine

+
+
+
+
+

2. Definição

+
+
+

📘"Garante que uma classe tenha apenas uma instância e fornece um ponto global de acesso a ela." [UCPP]

+
+
+

ucpp

+
+
+
+
+

3. Aplicabilidade

+
+
+
    +
  • +

    Quando precisa-se garantir que uma classe tenha uma única instância durante toda a execução da app;

    +
  • +
  • +

    o objeto a ser criado possui dados únicos, compartilhados por todos os usuários da app;

    +
  • +
  • +

    tal objeto exige muitos recursos (como memória) ou tem alto custo de instanciação;

    +
  • +
  • +

    representa um dispositivo físico pro qual não faz sentido ter duas instância dentro da mesma app (como uma impresora).

    +
  • +
+
+
+
+
+

4. Modelagem do Singleton

+
+
+

singleton

+
+
+
+
+

5. !

+
+
+

singleton

+
+
+
    +
  • +

    Aplicado a uma classe por vez.

    +
  • +
  • +

    A classe Singleton será a que aplicarmos o padrão.

    +
  • +
  • +

    Armazena instância única em um atributo estático e privado: instance.

    +
  • +
+
+
+
+
+

6. !

+
+
+

singleton

+
+
+
    +
  • +

    O atributo tem o tipo da própria classe.

    +
  • +
  • +

    getInstance(): estático, retorna a instância armazenada no atributo instance

    +
  • +
  • +

    Construtor privado.

    +
  • +
+
+
+
+
+

7. Princípios utilizados

+
+
+
    +
  • +

    Single-Responsitility Principle (SRP)?

    +
  • +
+
+
+
+background +
+
+
+
+
+

8. Exemplos de uso do Singleton

+
+
+
    +
  • +

    Classe para impressora fiscal em aplicação de PDV (Ponto de Venda).

    +
  • +
  • +

    Arquivo de configuração a ser utilizado por todo o sistema.

    +
  • +
+
+
+
+
+

9. Exemplos de uso do Singleton

+
+
+
    +
  • +

    Hibernate SessionFactory:

    +
  • +
  • +

    pesado

    +
  • +
  • +

    carrega as configurações (parse de XML) de acesso ao BD

    +
  • +
  • +

    cria sessões (conexões BD)

    +
  • +
  • +

    inicializa o Connection Pool

    +
  • +
+
+
+
+
+

10. Exemplos de uso do Singleton

+ +
+ +
+ + + + + \ No newline at end of file diff --git a/criacionais/04-builder/README.adoc b/criacionais/04-builder/README.adoc deleted file mode 100644 index a077171b9..000000000 --- a/criacionais/04-builder/README.adoc +++ /dev/null @@ -1,160 +0,0 @@ -:imagesdir: images/ -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Criacionais - -IMPORTANT: https://www.youtube.com/watch?v=l-ouMkReapo&list=PLyo0RUAM69UtO8Jjq71qgvRxcI2pTrB2m&index=11[Vídeo-aula sobre o padrão.] - -image:builder.png[title=https://www.clipartmax.com, link=https://www.clipartmax.com] - -== Builder (Construtor) - -=== Definição - -// tag::definicao1[] -📘"Separa a construção de um objeto complexo da sua representação, de modo que o mesmo processo de construção possa criar diferentes representações." (GoF) -// end::definicao1[] - -Em outras palavras, separa o código utilizado para a instanciação de objetos complexos do código da classe de tal objeto. As representações são as instâncias da classe. - -Outra definição diz que -// tag::definicao2[] -"O padrão Builder encapsula a construção de um objeto, permitindo que ele seja construído em passos." (UCPP) -// end::definicao2[] - -=== Distinção do Termo - -O padrão Builder significa construtor, mas não confunda com um método construtor existente em classes. -Apesar dos dois terem a mesma finalidade – construir, instanciar um objeto – são mecanismos diferentes utilizados para isso. Um Builder exige o uso de um método construtor. Ele não consegue instanciar um objeto por si só. - -=== Aplicabilidade - -O padrão pode ser usado pra instanciar um objeto complexo quando: - -// tag::aplicabilidade1[] -- A instanciação exige muitos parâmetros no construtor (normalmente bem mais que 3) image:construtor-excesso-params.png[] -- ... poucos parâmetros: preceito do Clean Code, favorece Programação Funcional. -// end::aplicabilidade1[] -// tag::aplicabilidade2[] -- A chamada vira uma linha infinita: image:construtor-excesso-params-chamada1.png[] -- E pode ser pior ainda em questões de legibilidade: image:construtor-excesso-params-chamada2.png[] -// end::aplicabilidade2[] -// tag::aplicabilidade3[] -- Poderíamos criar construtores sobrecarregados, mas a classe pode crescer muito e desviar o foco image:construtor-sobrecarregado.png[] -// end::aplicabilidade3[] -// tag::aplicabilidade4[] -- Há dependência entre atributos: se for definido valor pra _"x"_, precisa definir pra _"y"_. -- Existem atributos obrigatórios e outros opcionais. -- Regras de validação envolvem atributos em conjunto (pra validar _"x"_ é preciso verificar _"y"_ também), etc. -// end::aplicabilidade4[] - - -Normalmente o primeiro item já pode ser o suficiente para aplicarmos o padrão Builder a uma classe. - -=== Modelagem - -.Modelagem do Padrão Builder para uma classe fictícia "ClasseComplexa" -image::modelagem-builder.png[] - -No diagrama, a classe Builder foi representada como uma _Inner Class_: uma classe declarada dentro de outra. Se o código da `ClasseComplexa` for extenso, incluir a Builder como uma _Inner Class_ vai tornar o arquivo mais extenso ainda. Nestes casos, o ideal é criar a Builder em um arquivo separado. - -=== Princípios utilizados - -// tag::principios[] -- https://en.wikipedia.org/wiki/Separation_of_concerns[Separation of Concerns (SoC)] - Separação de Preocupações: separa as regras de negócio da classe do processo de instanciação da mesma. -- Alta Coesão -- https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)[General Responsibility Assignment Software Patterns] (GRASP) -// end::principios[] - -=== Exemplo de Uso - -A figura abaixo apresenta a modelagem do padrão Builder para a classe `Produto`. - -.Modelagem do padrão Builder para uma classe Produto -image::builder-produto.png[] - -=== Detalhes de Implementação - -// tag::implementacao[] -- Métodos na classe Builder: sem prefixo, `with` ou `set` -- set é o padrão de IDEs como IntelliJ e NetBeans -- Nome do método builder: `create()`, `createNomeObjeto()`, `newNomeObjeto()` ou `build()` -- Construtor _package_ ou _private_ -// end::implementacao[] - -=== Problemas / Desvantagens - -// tag::desvantagens[] -- *Duplicação absurda de código -- *Viola o princípio _Don't Repeat Yourself (DRY)_ -- *Novos atributos? Precisa atualizar a Builder! -- Exige a criação de um objeto Builder para poder instanciar os objetos desejados. -- Dificulta a injeção de dependências pela falta de um construtor sem parâmetros na classe cujos objetos serão instanciados. -// end::desvantagens[] - -NOTE: *Isto é um problema se a Builder for escrita manualmente. - -=== Soluções para Alguns dos Problemas - -Implementar o padrão Builder é algo cansativo. -A quantidade de código duplicado é absurda, pois todos -os atributos existentes na classe de modelo terá que existir -na classe Builder, assim como todos os setters. -Ao adicionar novos atributos, a classe Builder tem que ser atualizada. -Pra piorar, temos que repetir todo este processo para cada classe -que desejarmos aplicar o padrão. - -Quando você implementa o padrão como mostrado, você inclusive estará violando o princípio _Don't Repeat Yourself (DRY)_: Não Repita Você mesmo. Estamos repetindo a declaração dos atributos e setters ao criar uma Builder. - -Para evitar tais inconvenientes, podemos utilizar IDEs como o IntelliJ e NetBeans para gerar tais Builders automaticamente. https://youtu.be/vjVRDnra8-I[Este vídeo] mostra como isso pode ser feito. Neste caso, ao incluir um novo atributo, o mais fácil é excluir a builder e usar o IDE pra criá-la novamente. - -Alternativamente, podemos usar uma biblioteca que gera uma Builder quando percisarmos, se encarregando de atualizar automaticamente a Builder sempre que atualizarmos a classe de negócio que ele constrói. Uma biblioteca excelente para isto é a http://immutables.github.io/factory.html[Immutables], que dentre vários recursos, gera Builders por meio de uma simples anotação. - -Basta adicionar tal biblioteca no arquivo `pom.xml` e inclui a anotação `@Builder.Constructor` no construtor da classe desejada, como `Produto` e pronto: "automagicamente" a classe `ProdutoBuilder` é criada/atualizada quando compilamos o projeto. - -Veja um projeto de exemplo que cria uma builder para uma classe `Paciente` link:paciente-builder-automatico[aqui] (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/builder/paciente-builder-automatico[zip]) - -== Padrões Relacionados - -Padrões que possuem similaridades ou podem ser usados em conjunto: - -- link:../factory-method[Factory Method] - -== Exercícios - -Implemente uma classe `Produto` com os atributos abaixo. Utilize um construtor contendo apenas os parâmetros obrigatórios, marcados com asterisco: - -- id: long -- *titulo: String -- descricao: String -- marca: String -- modelo: String -- estoque: int (valor padrão zero) -- *preco: double (deve ser maior que zero) -- *dataCadastro: LocalDate (não pode ser menor que a data atual) -- *dataUltimaAtualizacao: LocalDate (não pode ser menor que a data atual) -- urlFoto: String -- *categoria: String -- peso: double -- altura: double -- largura: double -- profundidade: double - -O modelo só pode ser atribuído se a marca também for. -Há como resolver isso da forma como a implementação foi sugerida acima? - -Resolva o problema aplicando o padrão Builder, realizando as alterações necessárias na classe `Produto`. - -NOTE: Em uma aplicação mais realista, existiriam classes específicas como `Marca`, `Modelo`, `Categoria` e outras. Um `Modelo` estaria vinculado a uma `Marca`. Assim, na classe `Produto` teríamos apenas um atributo `Modelo`. Se este for setado, ele deveria estar vinculado a uma `Marca`. Mas este é apenas um exemplo didático simples, focando apenas na aplicação do Builder. diff --git a/criacionais/04-builder/README.html b/criacionais/04-builder/README.html new file mode 100644 index 000000000..3096a9e7e --- /dev/null +++ b/criacionais/04-builder/README.html @@ -0,0 +1,750 @@ + + + + + + + +Padrões de Projetos Criacionais + + + + + + + +
+
+
+
+ + + + + +
+ + +Vídeo-aula sobre o padrão. +
+
+
+

builder

+
+
+
+
+

1. Builder (Construtor)

+
+
+

1.1. Definição

+
+

📘"Separa a construção de um objeto complexo da sua representação, de modo que o mesmo processo de construção possa criar diferentes representações." (GoF)

+
+
+

Em outras palavras, separa o código utilizado para a instanciação de objetos complexos do código da classe de tal objeto. As representações são as instâncias da classe.

+
+
+

Outra definição diz que +"O padrão Builder encapsula a construção de um objeto, permitindo que ele seja construído em passos." (UCPP)

+
+
+
+

1.2. Distinção do Termo

+
+

O padrão Builder significa construtor, mas não confunda com um método construtor existente em classes. +Apesar dos dois terem a mesma finalidade – construir, instanciar um objeto – são mecanismos diferentes utilizados para isso. Um Builder exige o uso de um método construtor. Ele não consegue instanciar um objeto por si só.

+
+
+
+

1.3. Aplicabilidade

+
+

O padrão pode ser usado pra instanciar um objeto complexo quando:

+
+
+
    +
  • +

    A instanciação exige muitos parâmetros no construtor (normalmente bem mais que 3) construtor excesso params

    +
  • +
  • +

    …​ poucos parâmetros: preceito do Clean Code, favorece Programação Funcional.

    +
  • +
  • +

    A chamada vira uma linha infinita: construtor excesso params chamada1

    +
  • +
  • +

    E pode ser pior ainda em questões de legibilidade: construtor excesso params chamada2

    +
  • +
  • +

    Poderíamos criar construtores sobrecarregados, mas a classe pode crescer muito e desviar o foco construtor sobrecarregado

    +
  • +
  • +

    Há dependência entre atributos: se for definido valor pra "x", precisa definir pra "y".

    +
  • +
  • +

    Existem atributos obrigatórios e outros opcionais.

    +
  • +
  • +

    Regras de validação envolvem atributos em conjunto (pra validar "x" é preciso verificar "y" também), etc.

    +
  • +
+
+
+

Normalmente o primeiro item já pode ser o suficiente para aplicarmos o padrão Builder a uma classe.

+
+
+
+

1.4. Modelagem

+
+
+modelagem builder +
+
Figure 1. Modelagem do Padrão Builder para uma classe fictícia "ClasseComplexa"
+
+
+

No diagrama, a classe Builder foi representada como uma Inner Class: uma classe declarada dentro de outra. Se o código da ClasseComplexa for extenso, incluir a Builder como uma Inner Class vai tornar o arquivo mais extenso ainda. Nestes casos, o ideal é criar a Builder em um arquivo separado.

+
+
+
+

1.5. Princípios utilizados

+
+ +
+
+
+

1.6. Exemplo de Uso

+
+

A figura abaixo apresenta a modelagem do padrão Builder para a classe Produto.

+
+
+
+builder produto +
+
Figure 2. Modelagem do padrão Builder para uma classe Produto
+
+
+
+

1.7. Detalhes de Implementação

+
+
    +
  • +

    Métodos na classe Builder: sem prefixo, with ou set

    +
  • +
  • +

    set é o padrão de IDEs como IntelliJ e NetBeans

    +
  • +
  • +

    Nome do método builder: create(), createNomeObjeto(), newNomeObjeto() ou build()

    +
  • +
  • +

    Construtor package ou private

    +
  • +
+
+
+
+

1.8. Problemas / Desvantagens

+
+
    +
  • +

    *Duplicação absurda de código

    +
  • +
  • +

    *Viola o princípio Don’t Repeat Yourself (DRY)

    +
  • +
  • +

    *Novos atributos? Precisa atualizar a Builder!

    +
  • +
  • +

    Exige a criação de um objeto Builder para poder instanciar os objetos desejados.

    +
  • +
  • +

    Dificulta a injeção de dependências pela falta de um construtor sem parâmetros na classe cujos objetos serão instanciados.

    +
  • +
+
+
+ + + + + +
+ + +*Isto é um problema se a Builder for escrita manualmente. +
+
+
+
+

1.9. Soluções para Alguns dos Problemas

+
+

Implementar o padrão Builder é algo cansativo. +A quantidade de código duplicado é absurda, pois todos +os atributos existentes na classe de modelo terá que existir +na classe Builder, assim como todos os setters. +Ao adicionar novos atributos, a classe Builder tem que ser atualizada. +Pra piorar, temos que repetir todo este processo para cada classe +que desejarmos aplicar o padrão.

+
+
+

Quando você implementa o padrão como mostrado, você inclusive estará violando o princípio Don’t Repeat Yourself (DRY): Não Repita Você mesmo. Estamos repetindo a declaração dos atributos e setters ao criar uma Builder.

+
+
+

Para evitar tais inconvenientes, podemos utilizar IDEs como o IntelliJ e NetBeans para gerar tais Builders automaticamente. Este vídeo mostra como isso pode ser feito. Neste caso, ao incluir um novo atributo, o mais fácil é excluir a builder e usar o IDE pra criá-la novamente.

+
+
+

Alternativamente, podemos usar uma biblioteca que gera uma Builder quando percisarmos, se encarregando de atualizar automaticamente a Builder sempre que atualizarmos a classe de negócio que ele constrói. Uma biblioteca excelente para isto é a Immutables, que dentre vários recursos, gera Builders por meio de uma simples anotação.

+
+
+

Basta adicionar tal biblioteca no arquivo pom.xml e inclui a anotação @Builder.Constructor no construtor da classe desejada, como Produto e pronto: "automagicamente" a classe ProdutoBuilder é criada/atualizada quando compilamos o projeto.

+
+
+

Veja um projeto de exemplo que cria uma builder para uma classe Paciente aqui (zip)

+
+
+
+
+
+

2. Padrões Relacionados

+
+
+

Padrões que possuem similaridades ou podem ser usados em conjunto:

+
+
+ +
+
+
+
+

3. Exercícios

+
+
+

Implemente uma classe Produto com os atributos abaixo. Utilize um construtor contendo apenas os parâmetros obrigatórios, marcados com asterisco:

+
+
+
    +
  • +

    id: long

    +
  • +
  • +

    *titulo: String

    +
  • +
  • +

    descricao: String

    +
  • +
  • +

    marca: String

    +
  • +
  • +

    modelo: String

    +
  • +
  • +

    estoque: int (valor padrão zero)

    +
  • +
  • +

    *preco: double (deve ser maior que zero)

    +
  • +
  • +

    *dataCadastro: LocalDate (não pode ser menor que a data atual)

    +
  • +
  • +

    *dataUltimaAtualizacao: LocalDate (não pode ser menor que a data atual)

    +
  • +
  • +

    urlFoto: String

    +
  • +
  • +

    *categoria: String

    +
  • +
  • +

    peso: double

    +
  • +
  • +

    altura: double

    +
  • +
  • +

    largura: double

    +
  • +
  • +

    profundidade: double

    +
  • +
+
+
+

O modelo só pode ser atribuído se a marca também for. +Há como resolver isso da forma como a implementação foi sugerida acima?

+
+
+

Resolva o problema aplicando o padrão Builder, realizando as alterações necessárias na classe Produto.

+
+
+ + + + + +
+ + +Em uma aplicação mais realista, existiriam classes específicas como Marca, Modelo, Categoria e outras. Um Modelo estaria vinculado a uma Marca. Assim, na classe Produto teríamos apenas um atributo Modelo. Se este for setado, ele deveria estar vinculado a uma Marca. Mas este é apenas um exemplo didático simples, focando apenas na aplicação do Builder. +
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/04-builder/index.html b/criacionais/04-builder/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/04-builder/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/04-builder/paciente-builder-automatico-immutables/README.adoc b/criacionais/04-builder/paciente-builder-automatico-immutables/README.adoc deleted file mode 100755 index 46fe86e0b..000000000 --- a/criacionais/04-builder/paciente-builder-automatico-immutables/README.adoc +++ /dev/null @@ -1,22 +0,0 @@ -:imagesdir: ../../images/patterns/criacionais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Paciente Builder Automático usando biblioteca Immutables (https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/04-builder/paciente-builder-automatico-immutables[zip]) - -Mostra como usar a biblioteca http://immutables.github.io[Immutables] para gerar builders automáticos em tempo de compilação. -A builder é gerada na pasta target/generated-sources, assim, não é incluída -no código fonte do seu projeto (como no caso da geração pelo IDE). - - diff --git a/criacionais/04-builder/paciente-builder-automatico-immutables/README.html b/criacionais/04-builder/paciente-builder-automatico-immutables/README.html new file mode 100644 index 000000000..50d26ea21 --- /dev/null +++ b/criacionais/04-builder/paciente-builder-automatico-immutables/README.html @@ -0,0 +1,463 @@ + + + + + + + +Paciente Builder Automático usando biblioteca Immutables (zip) + + + + + + + +
+
+

Mostra como usar a biblioteca Immutables para gerar builders automáticos em tempo de compilação. +A builder é gerada na pasta target/generated-sources, assim, não é incluída +no código fonte do seu projeto (como no caso da geração pelo IDE).

+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/04-builder/paciente-builder-automatico-immutables/index.html b/criacionais/04-builder/paciente-builder-automatico-immutables/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/04-builder/paciente-builder-automatico-immutables/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/04-builder/paciente-builder-automatico-lombok/README.adoc b/criacionais/04-builder/paciente-builder-automatico-lombok/README.adoc deleted file mode 100755 index 1213fdc6a..000000000 --- a/criacionais/04-builder/paciente-builder-automatico-lombok/README.adoc +++ /dev/null @@ -1,28 +0,0 @@ -:imagesdir: ../../images/patterns/criacionais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Paciente Builder Automático com Biblioteca Lombok (https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/04-builder/paciente-builder-automatico-lombok[zip]) - -Mostra como usar a biblioteca http://projectlombok.org[Lombok] para gerar builders automáticos em tempo de compilação. -O Lombok intercepta o processo de compilação e alterar o bytecode das classes onde as anotações dele foram incluídas. -Assim, ele altera o arquivo .class e não gera qualquer arquivo .java como a biblioteca [Immutables](../paciente-builder-automatico-immutables). - -No entanto, como o IDE analisa o código fonte e não encontrará nenhum arquivo Java com a Builder, -ele não reconheceria tal classe que o Lombok gerou. Por isso, o uso do Lombok requer suporte do IDE, -que é feito pela instalação de uma extensão. No entanto, os IDEs e editores mais conhecidos como -NetBeans, IntelliJ e VS Code já vem com tal extensão instalada por padrão nas versões atuais. - - - diff --git a/criacionais/04-builder/paciente-builder-automatico-lombok/README.html b/criacionais/04-builder/paciente-builder-automatico-lombok/README.html new file mode 100644 index 000000000..27518d1ea --- /dev/null +++ b/criacionais/04-builder/paciente-builder-automatico-lombok/README.html @@ -0,0 +1,469 @@ + + + + + + + +Paciente Builder Automático com Biblioteca Lombok (zip) + + + + + + + +
+
+

Mostra como usar a biblioteca Lombok para gerar builders automáticos em tempo de compilação. +O Lombok intercepta o processo de compilação e alterar o bytecode das classes onde as anotações dele foram incluídas. +Assim, ele altera o arquivo .class e não gera qualquer arquivo .java como a biblioteca [Immutables](../paciente-builder-automatico-immutables).

+
+
+

No entanto, como o IDE analisa o código fonte e não encontrará nenhum arquivo Java com a Builder, +ele não reconheceria tal classe que o Lombok gerou. Por isso, o uso do Lombok requer suporte do IDE, +que é feito pela instalação de uma extensão. No entanto, os IDEs e editores mais conhecidos como +NetBeans, IntelliJ e VS Code já vem com tal extensão instalada por padrão nas versões atuais.

+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/04-builder/paciente-builder-automatico-lombok/index.html b/criacionais/04-builder/paciente-builder-automatico-lombok/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/04-builder/paciente-builder-automatico-lombok/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/04-builder/paciente-builder-base/README.adoc b/criacionais/04-builder/paciente-builder-base/README.adoc deleted file mode 100755 index 0eea9430f..000000000 --- a/criacionais/04-builder/paciente-builder-base/README.adoc +++ /dev/null @@ -1,18 +0,0 @@ -:imagesdir: ../../images/patterns/criacionais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Projeto base para implementação de uma classe Builder pelo IDE (https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/criacionais/04-builder/paciente-builder-base[zip]) - -Use o projeto para criar sua implementação de uma classe Builder para a classe Paciente. diff --git a/criacionais/04-builder/paciente-builder-base/README.html b/criacionais/04-builder/paciente-builder-base/README.html new file mode 100644 index 000000000..822b46c5a --- /dev/null +++ b/criacionais/04-builder/paciente-builder-base/README.html @@ -0,0 +1,461 @@ + + + + + + + +Projeto base para implementação de uma classe Builder pelo IDE (zip) + + + + + + + +
+
+

Use o projeto para criar sua implementação de uma classe Builder para a classe Paciente.

+
+
+ + + + + \ No newline at end of file diff --git a/criacionais/04-builder/paciente-builder-base/index.html b/criacionais/04-builder/paciente-builder-base/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/04-builder/paciente-builder-base/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/criacionais/04-builder/slides.adoc b/criacionais/04-builder/slides.adoc deleted file mode 100644 index c8b4bdca1..000000000 --- a/criacionais/04-builder/slides.adoc +++ /dev/null @@ -1,212 +0,0 @@ -//:revealjsdir: https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.8.0/ -:revealjsdir: https://unpkg.com/reveal.js@4.3.1 -//Não exibir notas para usuários -:revealjs_showNotes: false - -:revealjs_slideNumber: true -:source-highlighter: highlightjs -:icons: font -:allow-uri-read: -:imagesdir: images/ - -:safe: unsafe -//https://github.com/hakimel/reveal.js#theming -:revealjs_theme: league -:customcss: slides-base.css - -:numbered: -:toc: left -:toc-title: Sumário -:toclevels: 5 - -ifdef::env-github[] -//Exibe ícones para os blocos como NOTE e IMPORTANT no GitHub -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -elsedef::[] -endif::[] - -:chapter-label: -:listing-caption: Listagem -:figure-caption: Figura - -//Transição para todos os slides // none/fade/slide/convex/concave/zoom -//:revealjs_transition: 'zoom' - -= Builder Design Pattern image:builder.png[title=Imagem clipartmax.com] - -Prof. Manoel Campos - -image::https://manoelcampos.com/padroes-projetos/images/biolink.png[] - -[transition=zoom] -== Categoria - -Padrão de projeto criacional image:https://raw.githubusercontent.com/manoelcampos/padroes-projetos/master/images/ice-cream-sandwich-machine.gif[title=https://twistedsifter.com, link=https://twistedsifter.com/category/angifs/page/6/] - -[transition=fade] -== Definição - -include::README.adoc[tag=definicao1] - -image::https://raw.githubusercontent.com/manoelcampos/padroes-projetos/master/images/design-patterns-gof.jpg[width=25%] - -== Definição - -include::README.adoc[tag=definicao2] - -image::https://raw.githubusercontent.com/manoelcampos/padroes-projetos/master/images/ucpp.jpg[] - -[transition=fade] -== Distinção do Termo - -image:dictionary.png[] - -[%step] -- Builder = Construtor -- porém Builder != Método Construtor -- Builder exige um Método Construtor - -== Aplicabilidade - -[%step] -include::README.adoc[tag=aplicabilidade1] - -== Aplicabilidade - -[%step] -include::README.adoc[tag=aplicabilidade2] - -== Aplicabilidade - -include::README.adoc[tag=aplicabilidade3] - -== Aplicabilidade - -[%step] -include::README.adoc[tag=aplicabilidade4] - -[transition=zoom] -== Modelagem do Builder - -== ! - -image:modelagem-builder.png[width=50%] - -[%step] -- Builder foi representada como _Inner Class_ -- `ClasseComplexa` é extensa? Builder separado! - -[transition=zoom, background-opacity=0.4] -== Princípios utilizados - -[%step] -include::README.adoc[tag=principios] - -[transition=fade] -== Exemplo de Uso - -== ! - -image::builder-produto.png[background, size=contain] - -== Detalhes de Implementação - -[%step] -include::README.adoc[tag=implementacao] - -[transition=zoom] -== Problemas / Desvantagens - -[%step] -include::README.adoc[tag=desvantagens] - -== Soluções para Alguns dos Problemas - -[%step] -- IDEs como IntelliJ e NetBeans -- Bibliotecas que geram classes Builder: Immutables - http://immutables.github.io - -== Immutables - Dependência - -[source, xml] ----- - - - org.immutables - value - 2.9.2 - provided - - - org.immutables - builder - 2.9.2 - provided - ----- - -== ! -[source, java] ----- -public class Produto { - // Atributos da Classe, getters e setters - - @Builder.Constructor - Produto(long id, String titulo, String descricao, String marca, String modelo, int estoque, double preco, LocalDate dataCadatro, LocalDate dataUltimaAtualizacao, String urlFoto, String categoria, Vendedor vendedor, double peso, double altura, double largura, double profundidade) { - // Código do Construtor - } - - public static void main(String[] args) { - Produto produto = - new ProdutoBuilder() - .titulo("SmartTV LCD") - .categoria("Eletrônicos") - .estoque(100) - .preco(1280) - .urlFoto("/smart-tv.png") - .build(); - } -} ----- - -== Lombok - -[%step] -- Altera as classes compiladas: https://projectlombok.org/features/Builder - -== ! - -[source, java] ----- -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@Builder -public class Produto { - // Atributos da Classe - - public static void main(String[] args) { - Produto produto = - Produto.builder() - .titulo("SmartTV LCD") - .categoria("Eletrônicos") - .estoque(100) - .preco(1280) - .urlFoto("/smart-tv.png") - .build(); - } -} ----- - - -[transition=fade] -== Material e Projetos no GitHub - -https://bit.ly/2zOwSar diff --git a/criacionais/04-builder/slides.html b/criacionais/04-builder/slides.html new file mode 100644 index 000000000..9cc050c73 --- /dev/null +++ b/criacionais/04-builder/slides.html @@ -0,0 +1,829 @@ + + + + + + + +Builder Design Pattern + + + + + + + +
+
+
+
+

Prof. Manoel Campos

+
+
+
+biolink +
+
+
+
+
+

1. Categoria

+
+
+

Padrão de projeto criacional ice cream sandwich machine

+
+
+
+
+

2. Definição

+
+
+

📘"Separa a construção de um objeto complexo da sua representação, de modo que o mesmo processo de construção possa criar diferentes representações." (GoF)

+
+
+
+design patterns gof +
+
+
+
+
+

3. Definição

+
+
+

"O padrão Builder encapsula a construção de um objeto, permitindo que ele seja construído em passos." (UCPP)

+
+
+
+ucpp +
+
+
+
+
+

4. Distinção do Termo

+
+
+

dictionary

+
+
+
    +
  • +

    Builder = Construtor

    +
  • +
  • +

    porém Builder != Método Construtor

    +
  • +
  • +

    Builder exige um Método Construtor

    +
  • +
+
+
+
+
+

5. Aplicabilidade

+
+
+
    +
  • +

    A instanciação exige muitos parâmetros no construtor (normalmente bem mais que 3) construtor excesso params

    +
  • +
  • +

    …​ poucos parâmetros: preceito do Clean Code, favorece Programação Funcional.

    +
  • +
+
+
+
+
+

6. Aplicabilidade

+
+
+
    +
  • +

    A chamada vira uma linha infinita: construtor excesso params chamada1

    +
  • +
  • +

    E pode ser pior ainda em questões de legibilidade: construtor excesso params chamada2

    +
  • +
+
+
+
+
+

7. Aplicabilidade

+
+
+
    +
  • +

    Poderíamos criar construtores sobrecarregados, mas a classe pode crescer muito e desviar o foco construtor sobrecarregado

    +
  • +
+
+
+
+
+

8. Aplicabilidade

+
+
+
    +
  • +

    Há dependência entre atributos: se for definido valor pra "x", precisa definir pra "y".

    +
  • +
  • +

    Existem atributos obrigatórios e outros opcionais.

    +
  • +
  • +

    Regras de validação envolvem atributos em conjunto (pra validar "x" é preciso verificar "y" também), etc.

    +
  • +
+
+
+
+
+

9. Modelagem do Builder

+
+ +
+
+
+

10. !

+
+
+

modelagem builder

+
+
+
    +
  • +

    Builder foi representada como Inner Class

    +
  • +
  • +

    ClasseComplexa é extensa? Builder separado!

    +
  • +
+
+
+
+
+

11. Princípios utilizados

+
+
+ +
+
+
+
+

12. Exemplo de Uso

+
+ +
+
+
+

13. !

+
+
+
+background +
+
+
+
+
+

14. Detalhes de Implementação

+
+
+
    +
  • +

    Métodos na classe Builder: sem prefixo, with ou set

    +
  • +
  • +

    set é o padrão de IDEs como IntelliJ e NetBeans

    +
  • +
  • +

    Nome do método builder: create(), createNomeObjeto(), newNomeObjeto() ou build()

    +
  • +
  • +

    Construtor package ou private

    +
  • +
+
+
+
+
+

15. Problemas / Desvantagens

+
+
+
    +
  • +

    *Duplicação absurda de código

    +
  • +
  • +

    *Viola o princípio Don’t Repeat Yourself (DRY)

    +
  • +
  • +

    *Novos atributos? Precisa atualizar a Builder!

    +
  • +
  • +

    Exige a criação de um objeto Builder para poder instanciar os objetos desejados.

    +
  • +
  • +

    Dificulta a injeção de dependências pela falta de um construtor sem parâmetros na classe cujos objetos serão instanciados.

    +
  • +
+
+
+
+
+

16. Soluções para Alguns dos Problemas

+
+
+ +
+
+
+
+

17. Immutables - Dependência

+
+
+
+
<!-- http://immutables.github.io/factory.html -->
+<dependency>
+  <groupId>org.immutables</groupId>
+  <artifactId>value</artifactId>
+  <version>2.9.2</version>
+  <scope>provided</scope>
+</dependency>
+<dependency>
+  <groupId>org.immutables</groupId>
+  <artifactId>builder</artifactId>
+  <version>2.9.2</version>
+  <scope>provided</scope>
+</dependency>
+
+
+
+
+
+

18. !

+
+
+
+
public class Produto {
+    // Atributos da Classe, getters e setters
+
+    @Builder.Constructor
+    Produto(long id, String titulo, String descricao, String marca, String modelo, int estoque, double preco, LocalDate dataCadatro, LocalDate dataUltimaAtualizacao, String urlFoto, String categoria, Vendedor vendedor, double peso, double altura, double largura, double profundidade) {
+        // Código do Construtor
+    }
+
+    public static void main(String[] args) {
+        Produto produto =
+                new ProdutoBuilder()
+                        .titulo("SmartTV LCD")
+                        .categoria("Eletrônicos")
+                        .estoque(100)
+                        .preco(1280)
+                        .urlFoto("/smart-tv.png")
+                        .build();
+    }
+}
+
+
+
+
+
+

19. Lombok

+
+
+ +
+
+
+
+

20. !

+
+
+
+
import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Builder
+public class Produto {
+    // Atributos da Classe
+
+    public static void main(String[] args) {
+        Produto produto =
+            Produto.builder()
+                   .titulo("SmartTV LCD")
+                   .categoria("Eletrônicos")
+                   .estoque(100)
+                   .preco(1280)
+                   .urlFoto("/smart-tv.png")
+                   .build();
+    }
+}
+
+
+
+
+
+

21. Material e Projetos no GitHub

+ +
+
+ + + + + \ No newline at end of file diff --git a/criacionais/README.adoc b/criacionais/README.adoc deleted file mode 100644 index 474f2cc41..000000000 --- a/criacionais/README.adoc +++ /dev/null @@ -1,27 +0,0 @@ -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font -:imagesdir: ../images/ - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Criacionais - -image::ice-cream-sandwich-machine.gif[width=300] - -NOTE: https://www.youtube.com/watch?v=LwsC1rk6irM&list=PLyo0RUAM69UtO8Jjq71qgvRxcI2pTrB2m[Playlist de Padrões de Projetos Criacionais no YouTube] - -- link:01-simple-factory[Simple Factory (Fábrica Simples)] -- link:02-factory-method[Factory Method (Método Fábrica)] -- link:03-singleton[Singleton] -- link:04-builder[Builder (Construtor)] - -ifndef::env-github[image:back.png[alt=Voltar, link=../]] diff --git a/criacionais/README.html b/criacionais/README.html new file mode 100644 index 000000000..faacbdb77 --- /dev/null +++ b/criacionais/README.html @@ -0,0 +1,494 @@ + + + + + + + +Padrões de Projetos Criacionais + + + + + + + + + + + + + \ No newline at end of file diff --git a/criacionais/index.html b/criacionais/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/criacionais/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/01-adapter/README.adoc b/estruturais/01-adapter/README.adoc deleted file mode 100644 index 713f6b718..000000000 --- a/estruturais/01-adapter/README.adoc +++ /dev/null @@ -1,140 +0,0 @@ -:imagesdir: ../../images/patterns/estruturais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Estruturais - -== Adapter (Adaptador) - -IMPORTANT: https://youtu.be/G4Objgc6zxM[Vídeo-aula sobre o padrão.] - -.https://youtu.be/45I9jX5uO9A -https://youtu.be/45I9jX5uO9A[image:adapter-tomada.png[]] - - -=== Definição - -// tag::definicao[] -📘"O padrão adapter converte a interface de uma classe em outra interface que os clientes esperam. **Um adaptador permite que classes anteriormente incompatíveis possam trabalhar em conjunto**". <> -// end::definicao[] - -=== Aplicabilidade - -Um dos casos onde o adapter é amplamente aplicado é quando utiliza-se um determinado serviço web, framework ou biblioteca (que chamaremos de componente) onde existem diferentes implementações destes, cada uma funcionando de uma forma diferente. Logo, o código necessário para usar um determinado componente seria diferente de outro. Normalmente vão existir vários métodos com nomes e parâmetros diferentes (assinaturas). Assim, trocar tal componente por outro pode ser um trabalho complexo. - -Um adapter neste caso pode fornecer uma interface padrão a ser utilizada publicamente, encapsulando as diferenças entre as diferentes implementações dos componentes e permitindo a substituição de um componente por outro. - -Você também pode precisar fornecer um componente existente para ser utilizado por uma outra empresa, mas seu componente tem uma interface pública diferente do que tal empresa exige. Isto ocorre por exemplo, em sistemas de pagamento online disponibilizados por diversas empresas. Para que o seu sistema seja notificado se um pagamento foi confirmado, ele precisa fornecer um serviço com uma determinada interface. Assim, o sistema de pagamento interage com tal interface para notificar o seu sistema da confirmação do pagamento de um cliente. Alguns exemplos incluem o serviço do https://m.pagseguro.uol.com.br/v2/guia-de-integracao/api-de-notificacoes.html?_rnt=dd#v2-item-servico-de-notificacoes[PagSeguro] e PayPal. - -=== Modelagem do Padrão - -.Modelagem do padrão adapter -image::adapter.png[] - -Podemos ter 1 ou mais classes que precisam ser adaptadas, como as classes `AdaptadaAbc` e `AdaptadaXyz`. -Cada uma dessas classes fornece uma implementação diferente de uma determinada funcionalidade. -Por exemplo, cada classe pode representar o acesso a um determinado serviço na web, -como obtenção da previsão do tempo. Cada uma obtém a previsão de um serviço (site) diferente. -Podemos ter vários métodos diferentes que fornecem as mesmas funcionalidades, como obtenção da previsão para uma determinada data, média de temperatura para um determinado mês do ano, umidade relativa do ar, etc. No entanto, os métodos, parâmetros e tipos em cada uma dessas classes (como possivelmente foram implementadas por pessoas/equipes distintas), serão diferentes. - -Para padronizarmos tais métodos e assim tornar idêntica a forma de usar qualquer uma dessas classes, devemos implementar um adaptador para cada classe a ser adaptada. No diagrama de exemplo, a classe `AdaptadaAbc` possui os métodos `metodoA()` e `metodoB()`. Já a classe `AdaptadaXyz` possui os métodos `metodoX()` e `metodoY()`. A padronização pode ser feita pela criação de uma interface comum (`Alvo`) que será implementada por cada adaptador. O nome de cada classe Adapter normalmente é formado pelo nome da classe a ser adaptada, seguido da palavra `Adapter`. Assim, temos as classes `AbcAdapter` e `XyzAdapter` para o modelo apresentado. Uma classe `AbcAdapter` que implementa a interface `Alvo` é um adaptador para a classe `AdaptadaAbc`. Em outras palavras, ela adapta objetos `AdaptadaAbc` para funcionarem como se fossem do tipo `Alvo`. - -`Cliente` é uma classe qualquer que vai usar esta interface para se comunicar com os objetos adaptados por meio de seus adaptadores. -Assim, se a classe `Cliente` precisar trocar um objeto por outro, como o objeto será acessado por meio da interface `Alvo`, não precisaremos alterar a forma de utilizar um novo objeto. - -Observe que, por exemplo, o `metodo1()` na classe `AbcAdapter` vai apenas delegar a chamada ao `metodoA()` de um objeto `AbcAdapter`. - -Um projeto de exemplo para o diagrama apresentado está disponível link:modelagem[aqui]. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão. - -Você pode entender melhor o diagrama da Figura 1 fazendo uma analogia com o adaptador de tomada como a Figura 2 abaixo. - -.Analogia da Modelagem do Padrão Adapter com um Adaptador de Tomada -image::adapter-analogia-tomada.png[] - -=== Exemplos Práticos - -.Modelagem fictícia de adaptadores para sistemas de pagamento online -image::sistemas-pagamento-adapters.png[] - -A geração de números aleatórios utilizando serviços web como http://random.org e http://random.irb.hr também é outro exemplo onde adapters podem ser criados. -Tais serviços geram números verdadeiramente aleatórios usando, por exemplo, dados meteorológicos. -No entanto, cada serviço implementa uma API diferente, com parâmetros e tipos de retorno distintos. -Para trocar um serviço por outro em uma aplicação, é preciso alterar o código -da aplicação por causa das diferenças na API. - -=== Princípios utilizados - -- https://en.wikipedia.org/wiki/Single_responsibility_principle[Single Responsibility Principle (SRP)] pois cada adaptador criado possui uma responsabilidade única: tornar uma classe a ser adaptada compatível com a interface alvo. -- https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)], pois se uma nova classe precisar ser adaptada, basta criar um novo adaptador implementando a interface alvo. Não precisamos alterar nenhum código existente. -- https://en.wikipedia.org/wiki/Liskov_substitution_principle[Liskov Substitution Principle (LSP)] pois em qualquer lugar que a interface alvo puder ser usada, podemos usar um adaptador pra qualquer uma das classes adaptadas. A Figura 4 mostra como o princípio se aplica. -- https://en.wikipedia.org/wiki/Dependency_inversion_principle[Dependency Inversion Principle (DIP)]: ao usar somente a interface alvo para declarar variáveis e não as classes adaptadas, passamos a depender de uma abstração e não de implementações. Com isto, os relacionamentos de dependência são invertidos: no lugar de o cliente depender de cada uma das implementações, ele depende apenas do tipo abstrato (a interface alvo). O cliente nem precisa saber da existência das classes concretas. Reveja a Figura 1 para entender o relacionamento de dependência. -- https://tuhrig.de/programming-to-an-interface/[Programar para uma interface não uma implementação] (GoF): como o código do cliente vai depender apenas da interface alvo, estaremos "programando para uma interface, não uma implementação". - -.Princípio LSP com o padrão Adapter: se tivermos um adaptador para cada um dos diferentes tipos de plug, podemos usar qualquer um deles com uma tomada específica. -image::adapter-analogia-varios.png[] - -== Padrões Relacionados - -- Decorator - -== Onde o padrão é usado no JDK e outros lugares - -No JDK, apesar de não estar explícito pelo nome, temos adapters implementados como métodos. Exemplos incluem: - -- `java.util.Arrays#asList()`: a partir de um array, retorna uma nova instância de um adaptador para List. -- `java.util.Collections#list()`: a partir de uma coleção qualquer como conjuntos (Set), filas (Queue), -- https://docs.oracle.com/javase/8/javafx/api/javafx/beans/property/adapter/package-summary.html[um pacote inteiro de adapters para aplicações Desktop com JavaFX] - -Bibliotecas para geração de logs em aplicações são um exemplo onde o Adapter e outros padrões (como o Facade) são usados. -Você pode nunca ter usado uma biblioteca destas em Java ou qualquer linguagem, mas pode ter certeza que -precisará. Log é um recurso essencial em qualquer aplicação rodando em produção. - -A https://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html[java.util.logging (JUL)] é um dos casos onde uma biblioteca fornecida pelo JDK possui recursos limitados e outras surgiram justamente para resolver tais problemas, como a https://logging.apache.org/log4j/[Apache Log4J]. Existem algumas outras bibliotecas de log para Java, mas incompatíveis entre si. -Por esta causa, o adaptador https://logging.apache.org/log4j/log4j-2.7/log4j-jul/index.html[Apache Log4J JUL Adapter] permite utilizar a Log4J no lugar da JUL, sem precisar alterar o código da aplicação. - -=== Pensando em interfaces como adaptadores - -Em um classe que implementa múltiplas interfaces, podemos pensar na classe como sendo um adaptador para todas estas interfaces. Apesar de nem sempre o padrão Adapter está sendo de fato implementado nestes casos, ao pensar assim, podemos ter alguns benefícios. - -Na Java Collections Framework (JCF), classes como ArrayList e LinkedList funcionam como adaptadores para a interface List. Assim, no lugar de declarar os tipos concretos, usamos a interface List no lugar. Assim, em qualquer lugar que for exigido uma List, podemos passar um "adaptador" como ArrayList ou LinkedList. Internamente, estas classes podem ter métodos com nomes e assinaturas diferentes, mas como elas implementam os métodos de List, as diferenças internas são encapsuladas. -Por exemplo, na classe ArrayList utiliza-se `elementData(index)` para acessar um elemento -em uma determinada posição. Na classe LinkedList utiliza-se `node(index).item`. -Mesmo as duas classes fazerem parte da mesma framework (a JCF), elas representam estruturas -de dados muito diferentes. Para tornar seu uso uniforme para nós desenvolvedores, -os métodos citados não são públicos. Temos o `public E get(int index)` em tais classes, -que é herdado da interface `List`. Tal método padroniza o acesso aos elementos. - -Classes como ArrayList e LinkedList implementam múltiplas interfaces em uma hierarquia como List -> Collection -> Iterable. Tal hierarquia nos permite usar um ArrayList como se fosse um objeto List, Collection ou Iterable, de acordo com suas necessidades. - -Como exemplo, veja o seguinte método com uma implementação não ideal: - -[source,java] ----- -private void imprimir(ArrayList elementos){ - for (Double e : elementos) { - System.out.println(e); - } - - elementos.clear(); -} ----- - -Como pode ver, o método recebe um ArrayList, imprime todos os valores e apaga seus elementos. -Pense em como podemos criar 3 diferentes versões deste método para: - -1. imprimir qualquer tipo de lista (ArrayList, LinkedList, etc) -2. impedir que a lista seja modificada (por exemplo, pela remoção de elementos) -3. imprimir qualquer tipo de coleção (ArrayList, LinkedList, HashSet, TreeSet, etc) - -TIP: Analise a árvore hierarquica dos tipos mencionados e quais métodos públicos eles fornecem para resolver os 3 problemas acima. Você começar analisando a hierarquia da classe https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html[ArrayList em sua documentação]. diff --git a/estruturais/01-adapter/README.html b/estruturais/01-adapter/README.html new file mode 100644 index 000000000..2a7cd9c32 --- /dev/null +++ b/estruturais/01-adapter/README.html @@ -0,0 +1,682 @@ + + + + + + + +Padrões de Projetos Estruturais + + + + + + + +
+
+

1. Adapter (Adaptador)

+
+
+ + + + + +
+ + +Vídeo-aula sobre o padrão. +
+
+ +
+

1.1. Definição

+
+

📘"O padrão adapter converte a interface de uma classe em outra interface que os clientes esperam. Um adaptador permite que classes anteriormente incompatíveis possam trabalhar em conjunto". [UCPP]

+
+
+
+

1.2. Aplicabilidade

+
+

Um dos casos onde o adapter é amplamente aplicado é quando utiliza-se um determinado serviço web, framework ou biblioteca (que chamaremos de componente) onde existem diferentes implementações destes, cada uma funcionando de uma forma diferente. Logo, o código necessário para usar um determinado componente seria diferente de outro. Normalmente vão existir vários métodos com nomes e parâmetros diferentes (assinaturas). Assim, trocar tal componente por outro pode ser um trabalho complexo.

+
+
+

Um adapter neste caso pode fornecer uma interface padrão a ser utilizada publicamente, encapsulando as diferenças entre as diferentes implementações dos componentes e permitindo a substituição de um componente por outro.

+
+
+

Você também pode precisar fornecer um componente existente para ser utilizado por uma outra empresa, mas seu componente tem uma interface pública diferente do que tal empresa exige. Isto ocorre por exemplo, em sistemas de pagamento online disponibilizados por diversas empresas. Para que o seu sistema seja notificado se um pagamento foi confirmado, ele precisa fornecer um serviço com uma determinada interface. Assim, o sistema de pagamento interage com tal interface para notificar o seu sistema da confirmação do pagamento de um cliente. Alguns exemplos incluem o serviço do PagSeguro e PayPal.

+
+
+
+

1.3. Modelagem do Padrão

+
+
+adapter +
+
Figure 1. Modelagem do padrão adapter
+
+
+

Podemos ter 1 ou mais classes que precisam ser adaptadas, como as classes AdaptadaAbc e AdaptadaXyz. +Cada uma dessas classes fornece uma implementação diferente de uma determinada funcionalidade. +Por exemplo, cada classe pode representar o acesso a um determinado serviço na web, +como obtenção da previsão do tempo. Cada uma obtém a previsão de um serviço (site) diferente. +Podemos ter vários métodos diferentes que fornecem as mesmas funcionalidades, como obtenção da previsão para uma determinada data, média de temperatura para um determinado mês do ano, umidade relativa do ar, etc. No entanto, os métodos, parâmetros e tipos em cada uma dessas classes (como possivelmente foram implementadas por pessoas/equipes distintas), serão diferentes.

+
+
+

Para padronizarmos tais métodos e assim tornar idêntica a forma de usar qualquer uma dessas classes, devemos implementar um adaptador para cada classe a ser adaptada. No diagrama de exemplo, a classe AdaptadaAbc possui os métodos metodoA() e metodoB(). Já a classe AdaptadaXyz possui os métodos metodoX() e metodoY(). A padronização pode ser feita pela criação de uma interface comum (Alvo) que será implementada por cada adaptador. O nome de cada classe Adapter normalmente é formado pelo nome da classe a ser adaptada, seguido da palavra Adapter. Assim, temos as classes AbcAdapter e XyzAdapter para o modelo apresentado. Uma classe AbcAdapter que implementa a interface Alvo é um adaptador para a classe AdaptadaAbc. Em outras palavras, ela adapta objetos AdaptadaAbc para funcionarem como se fossem do tipo Alvo.

+
+
+

Cliente é uma classe qualquer que vai usar esta interface para se comunicar com os objetos adaptados por meio de seus adaptadores. +Assim, se a classe Cliente precisar trocar um objeto por outro, como o objeto será acessado por meio da interface Alvo, não precisaremos alterar a forma de utilizar um novo objeto.

+
+
+

Observe que, por exemplo, o metodo1() na classe AbcAdapter vai apenas delegar a chamada ao metodoA() de um objeto AbcAdapter.

+
+
+

Um projeto de exemplo para o diagrama apresentado está disponível aqui. Ele deve ser alterado para incluir as mudanças necessárias para o problema específico que você estiver resolvendo com o padrão.

+
+
+

Você pode entender melhor o diagrama da Figura 1 fazendo uma analogia com o adaptador de tomada como a Figura 2 abaixo.

+
+
+
+adapter analogia tomada +
+
Figure 2. Analogia da Modelagem do Padrão Adapter com um Adaptador de Tomada
+
+
+
+

1.4. Exemplos Práticos

+
+
+sistemas pagamento adapters +
+
Figure 3. Modelagem fictícia de adaptadores para sistemas de pagamento online
+
+
+

A geração de números aleatórios utilizando serviços web como http://random.org e http://random.irb.hr também é outro exemplo onde adapters podem ser criados. +Tais serviços geram números verdadeiramente aleatórios usando, por exemplo, dados meteorológicos. +No entanto, cada serviço implementa uma API diferente, com parâmetros e tipos de retorno distintos. +Para trocar um serviço por outro em uma aplicação, é preciso alterar o código +da aplicação por causa das diferenças na API.

+
+
+
+

1.5. Princípios utilizados

+
+
    +
  • +

    Single Responsibility Principle (SRP) pois cada adaptador criado possui uma responsabilidade única: tornar uma classe a ser adaptada compatível com a interface alvo.

    +
  • +
  • +

    Open/Closed Principle (OCP), pois se uma nova classe precisar ser adaptada, basta criar um novo adaptador implementando a interface alvo. Não precisamos alterar nenhum código existente.

    +
  • +
  • +

    Liskov Substitution Principle (LSP) pois em qualquer lugar que a interface alvo puder ser usada, podemos usar um adaptador pra qualquer uma das classes adaptadas. A Figura 4 mostra como o princípio se aplica.

    +
  • +
  • +

    Dependency Inversion Principle (DIP): ao usar somente a interface alvo para declarar variáveis e não as classes adaptadas, passamos a depender de uma abstração e não de implementações. Com isto, os relacionamentos de dependência são invertidos: no lugar de o cliente depender de cada uma das implementações, ele depende apenas do tipo abstrato (a interface alvo). O cliente nem precisa saber da existência das classes concretas. Reveja a Figura 1 para entender o relacionamento de dependência.

    +
  • +
  • +

    Programar para uma interface não uma implementação (GoF): como o código do cliente vai depender apenas da interface alvo, estaremos "programando para uma interface, não uma implementação".

    +
  • +
+
+
+
+adapter analogia varios +
+
Figure 4. Princípio LSP com o padrão Adapter: se tivermos um adaptador para cada um dos diferentes tipos de plug, podemos usar qualquer um deles com uma tomada específica.
+
+
+
+
+
+

2. Padrões Relacionados

+
+
+
    +
  • +

    Decorator

    +
  • +
+
+
+
+
+

3. Onde o padrão é usado no JDK e outros lugares

+
+
+

No JDK, apesar de não estar explícito pelo nome, temos adapters implementados como métodos. Exemplos incluem:

+
+
+ +
+
+

Bibliotecas para geração de logs em aplicações são um exemplo onde o Adapter e outros padrões (como o Facade) são usados. +Você pode nunca ter usado uma biblioteca destas em Java ou qualquer linguagem, mas pode ter certeza que +precisará. Log é um recurso essencial em qualquer aplicação rodando em produção.

+
+
+

A java.util.logging (JUL) é um dos casos onde uma biblioteca fornecida pelo JDK possui recursos limitados e outras surgiram justamente para resolver tais problemas, como a Apache Log4J. Existem algumas outras bibliotecas de log para Java, mas incompatíveis entre si. +Por esta causa, o adaptador Apache Log4J JUL Adapter permite utilizar a Log4J no lugar da JUL, sem precisar alterar o código da aplicação.

+
+
+

3.1. Pensando em interfaces como adaptadores

+
+

Em um classe que implementa múltiplas interfaces, podemos pensar na classe como sendo um adaptador para todas estas interfaces. Apesar de nem sempre o padrão Adapter está sendo de fato implementado nestes casos, ao pensar assim, podemos ter alguns benefícios.

+
+
+

Na Java Collections Framework (JCF), classes como ArrayList e LinkedList funcionam como adaptadores para a interface List. Assim, no lugar de declarar os tipos concretos, usamos a interface List no lugar. Assim, em qualquer lugar que for exigido uma List, podemos passar um "adaptador" como ArrayList ou LinkedList. Internamente, estas classes podem ter métodos com nomes e assinaturas diferentes, mas como elas implementam os métodos de List, as diferenças internas são encapsuladas. +Por exemplo, na classe ArrayList utiliza-se elementData(index) para acessar um elemento +em uma determinada posição. Na classe LinkedList utiliza-se node(index).item. +Mesmo as duas classes fazerem parte da mesma framework (a JCF), elas representam estruturas +de dados muito diferentes. Para tornar seu uso uniforme para nós desenvolvedores, +os métodos citados não são públicos. Temos o public E get(int index) em tais classes, +que é herdado da interface List. Tal método padroniza o acesso aos elementos.

+
+
+

Classes como ArrayList e LinkedList implementam múltiplas interfaces em uma hierarquia como List → Collection → Iterable. Tal hierarquia nos permite usar um ArrayList como se fosse um objeto List, Collection ou Iterable, de acordo com suas necessidades.

+
+
+

Como exemplo, veja o seguinte método com uma implementação não ideal:

+
+
+
+
private void imprimir(ArrayList<Double> elementos){
+    for (Double e : elementos) {
+        System.out.println(e);
+    }
+
+    elementos.clear();
+}
+
+
+
+

Como pode ver, o método recebe um ArrayList, imprime todos os valores e apaga seus elementos. +Pense em como podemos criar 3 diferentes versões deste método para:

+
+
+
    +
  1. +

    imprimir qualquer tipo de lista (ArrayList, LinkedList, etc)

    +
  2. +
  3. +

    impedir que a lista seja modificada (por exemplo, pela remoção de elementos)

    +
  4. +
  5. +

    imprimir qualquer tipo de coleção (ArrayList, LinkedList, HashSet, TreeSet, etc)

    +
  6. +
+
+
+ + + + + +
+ + +Analise a árvore hierarquica dos tipos mencionados e quais métodos públicos eles fornecem para resolver os 3 problemas acima. Você começar analisando a hierarquia da classe ArrayList em sua documentação. +
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/estruturais/01-adapter/captcha-adapters-v1/README.adoc b/estruturais/01-adapter/captcha-adapters-v1/README.adoc deleted file mode 100644 index 505606af7..000000000 --- a/estruturais/01-adapter/captcha-adapters-v1/README.adoc +++ /dev/null @@ -1,19 +0,0 @@ -:numbered: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Implementa Adapters para bibliotecas de captcha em Java (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/estruturais/01-adapter/captcha-adapters[zip]) - -O projeto padroniza diferentes bibliotecas de geração de captcha offline, -aplicando o padrão de projetos Adapter. As bibliotecas adaptadas são: - -- https://github.com/mewebstudio/java-captcha-generator[Java Captcha Generator] -- https://github.com/logicsquad/nanocaptcha[Nano Captcha] diff --git a/estruturais/01-adapter/captcha-adapters-v1/README.html b/estruturais/01-adapter/captcha-adapters-v1/README.html new file mode 100644 index 000000000..b2c805cbf --- /dev/null +++ b/estruturais/01-adapter/captcha-adapters-v1/README.html @@ -0,0 +1,464 @@ + + + + + + + +Implementa Adapters para bibliotecas de captcha em Java (zip) + + + + + + +
+
+

O projeto padroniza diferentes bibliotecas de geração de captcha offline, +aplicando o padrão de projetos Adapter. As bibliotecas adaptadas são:

+
+ +
+ + + \ No newline at end of file diff --git a/estruturais/01-adapter/captcha-adapters-v1/index.html b/estruturais/01-adapter/captcha-adapters-v1/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/01-adapter/captcha-adapters-v1/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/01-adapter/captcha-adapters-v2-template-method/README.adoc b/estruturais/01-adapter/captcha-adapters-v2-template-method/README.adoc deleted file mode 100644 index 4baa1cfa0..000000000 --- a/estruturais/01-adapter/captcha-adapters-v2-template-method/README.adoc +++ /dev/null @@ -1,21 +0,0 @@ -:numbered: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Implementa Adapters para bibliotecas de captcha em Java (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/estruturais/01-adapter/captcha-adapters[zip]) - -O projeto padroniza diferentes bibliotecas de geração de captcha offline, -aplicando o padrão de projetos Adapter. As bibliotecas adaptadas são: - -- https://github.com/mewebstudio/java-captcha-generator[Java Captcha Generator] -- https://github.com/logicsquad/nanocaptcha[Nano Captcha] - -Adicionalmente, ele aplica o padrão Template Method para remover duplicação de código. diff --git a/estruturais/01-adapter/captcha-adapters-v2-template-method/README.html b/estruturais/01-adapter/captcha-adapters-v2-template-method/README.html new file mode 100644 index 000000000..f2336a2cc --- /dev/null +++ b/estruturais/01-adapter/captcha-adapters-v2-template-method/README.html @@ -0,0 +1,467 @@ + + + + + + + +Implementa Adapters para bibliotecas de captcha em Java (zip) + + + + + + +
+
+

O projeto padroniza diferentes bibliotecas de geração de captcha offline, +aplicando o padrão de projetos Adapter. As bibliotecas adaptadas são:

+
+ +
+

Adicionalmente, ele aplica o padrão Template Method para remover duplicação de código.

+
+
+ + + \ No newline at end of file diff --git a/estruturais/01-adapter/captcha-adapters-v2-template-method/index.html b/estruturais/01-adapter/captcha-adapters-v2-template-method/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/01-adapter/captcha-adapters-v2-template-method/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/README.adoc b/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/README.adoc deleted file mode 100755 index 2cee63590..000000000 --- a/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/README.adoc +++ /dev/null @@ -1,22 +0,0 @@ -:source-highlighter: highlightjs -:numbered: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Adapters para Web APIs de CEPs com Spring (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/estruturais/adapter/01-cepservice-clients-adapter-spring-v1-manual[zip]) - -Mostra como criar manualmente adapters para APIs Web de consulta de endereço pelo CEP. -Apesar de o projeto estar adaptando o acesso aos serviços de CEP (criando classes cliente para estes serviços), -a implementação não segue o que convencionalmente vemos para o padrão Adapter, -por conta das especificidades do problema. - -=== Outros serviços para implementar - -- https://apicep.com -> Exemplo: https://cdn.apicep.com/file/apicep/77021-090.json diff --git a/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/README.html b/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/README.html new file mode 100644 index 000000000..c134c9b0c --- /dev/null +++ b/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/README.html @@ -0,0 +1,477 @@ + + + + + + + +Adapters para Web APIs de CEPs com Spring (zip) + + + + + + +
+
+
+
+

Mostra como criar manualmente adapters para APIs Web de consulta de endereço pelo CEP. +Apesar de o projeto estar adaptando o acesso aos serviços de CEP (criando classes cliente para estes serviços), +a implementação não segue o que convencionalmente vemos para o padrão Adapter, +por conta das especificidades do problema.

+
+
+
+
+

1. Outros serviços para implementar

+ +
+
+ + + + + \ No newline at end of file diff --git a/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/index.html b/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/01-adapter/cepservice-clients-adapter-spring-v1-manual/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/README.adoc b/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/README.adoc deleted file mode 100644 index 1f4a70bf6..000000000 --- a/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/README.adoc +++ /dev/null @@ -1,17 +0,0 @@ -= Injeção de Dependência e clientes de API com Spring (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico[zip]) - - -Projeto mostra como usar injeção de dependência no Spring e criação de clientes de API automaticamente com https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/[OpenFeign]. - -O OpenFeign cria clientes para APIs web de forma automática, simplesmente definindo-se uma interface e utilizando as mesmas anotações que usumos para criar um controller https://spring.io/guides/tutorials/rest/[REST]. -As devidas dependências foram adicionadas no pom.xml. -Mas para que o OpenFeign consiga implementar as interfaces -para estas APIs web, é preciso que a classe da aplicação, -neste caso a link:src/main/java/io/github/manoelcampos/cepservices/CepservicesApplication.java[CepservicesApplication] tenha a anotação -`@EnableFeignClients`. - -É utilizada a biblioteca https://projectlombok.org[Lombok] para reduzir bastante a necessidade de escrita de código rotineiro, como construtores, _getters_ e _setters_ (_boilerplate code_). - -Apesar de o projeto estar adaptando o acesso aos serviços de CEP (criando classes cliente para estes serviços), -a implementação não segue o que convencionalmente vemos para o padrão Adapter, -por conta das especificidades do problema e, neste caso, principalmente pelas bibliotecas utilizadas. diff --git a/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/README.html b/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/README.html new file mode 100644 index 000000000..2c11d200b --- /dev/null +++ b/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/README.html @@ -0,0 +1,468 @@ + + + + + + + +Injeção de Dependência e clientes de API com Spring (zip) + + + + + +
+
+

Projeto mostra como usar injeção de dependência no Spring e criação de clientes de API automaticamente com OpenFeign.

+
+
+

O OpenFeign cria clientes para APIs web de forma automática, simplesmente definindo-se uma interface e utilizando as mesmas anotações que usumos para criar um controller REST. +As devidas dependências foram adicionadas no pom.xml. +Mas para que o OpenFeign consiga implementar as interfaces +para estas APIs web, é preciso que a classe da aplicação, +neste caso a CepservicesApplication tenha a anotação +@EnableFeignClients.

+
+
+

É utilizada a biblioteca Lombok para reduzir bastante a necessidade de escrita de código rotineiro, como construtores, getters e setters (boilerplate code).

+
+
+

Apesar de o projeto estar adaptando o acesso aos serviços de CEP (criando classes cliente para estes serviços), +a implementação não segue o que convencionalmente vemos para o padrão Adapter, +por conta das especificidades do problema e, neste caso, principalmente pelas bibliotecas utilizadas.

+
+
+ + + \ No newline at end of file diff --git a/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/index.html b/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/01-adapter/cepservice-clients-adapter-spring-v2-automatico/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/01-adapter/index.html b/estruturais/01-adapter/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/01-adapter/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/01-adapter/modelagem/README.adoc b/estruturais/01-adapter/modelagem/README.adoc deleted file mode 100644 index ad8029551..000000000 --- a/estruturais/01-adapter/modelagem/README.adoc +++ /dev/null @@ -1,10 +0,0 @@ -:imagesdir: ../../../images/patterns/estruturais - -= Modelagem do Padrão Adapter (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/estruturais/adapter/modelagem/[zip]) - -Apresenta um código de exemplo da modelagem do padrão Adapter. -Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. -Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos. - -.Modelagem do padrão adapter -image::adapter.png[] \ No newline at end of file diff --git a/estruturais/01-adapter/modelagem/README.html b/estruturais/01-adapter/modelagem/README.html new file mode 100644 index 000000000..fbd9d3c50 --- /dev/null +++ b/estruturais/01-adapter/modelagem/README.html @@ -0,0 +1,460 @@ + + + + + + + +Modelagem do Padrão Adapter (zip) + + + + + +
+
+

Apresenta um código de exemplo da modelagem do padrão Adapter. +Tal código serve apenas de base para implementação de uma solução específica utilizando o padrão. +Assim, nomes de classes, métodos e atributos precisam ser alterados para nomes específicos.

+
+
+
+adapter +
+
Figure 1. Modelagem do padrão adapter
+
+
+ + + \ No newline at end of file diff --git a/estruturais/01-adapter/modelagem/index.html b/estruturais/01-adapter/modelagem/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/01-adapter/modelagem/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/01-adapter/slides.adoc b/estruturais/01-adapter/slides.adoc deleted file mode 100644 index dd3d0510b..000000000 --- a/estruturais/01-adapter/slides.adoc +++ /dev/null @@ -1,151 +0,0 @@ -//:revealjsdir: https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.8.0/ -:revealjsdir: https://unpkg.com/reveal.js@4.3.1 -:revealjs_slideNumber: true -:source-highlighter: highlightjs -:icons: font -:allow-uri-read: -:imagesdir: ../../images -:stylesheet: ../../adoc-golo.css -:customcss: ../../slides-base.css -:numbered: -:toc: left -:toc-title: Sumário -:toclevels: 5 - -ifdef::env-github[] -//Exibe ícones para os blocos como NOTE e IMPORTANT no GitHub - -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -:chapter-label: -:listing-caption: Listagem -:figure-caption: Figura - -//Transição para todos os slides // none/fade/slide/convex/concave/zoom -//:revealjs_transition: 'zoom' - -//https://github.com/hakimel/reveal.js#theming -:revealjs_theme: league - -= Padrão de Projetos Adapter image:patterns/estruturais/adapter-tomada.png[] - - -Prof. Manoel Campos - -image::https://manoelcampos.com/padroes-projetos/images/biolink.png[] - -[transition=zoom] -== Categoria - -Padrão de projeto estrutural image:building-structure.jpg[] - -[transition=fade] -== Definição - -include::README.adoc[tag=definicao] - -image:ucpp.jpg[size=contain] - -[transition=zoofadem] -== Aplicabilidade - -Quando: - -[%step] -- utiliza-se um determinado serviço web, framework ou biblioteca (componente) onde existem implementações incompatíveis destes e deseja-se ser capaz de trocar um componente por outro; -- integração de componentes existentes com sistemas de outras empresas. Exemplos incluem sistemas de pagamento como https://m.pagseguro.uol.com.br/v2/guia-de-integracao/api-de-notificacoes.html?_rnt=dd#v2-item-servico-de-notificacoes[PagSeguro] e PayPal. - - -[transition=zoom] -== Modelagem do Adapter - -== ! - -image::patterns/estruturais/adapter.png[background, size=contain] - -[transition=zoom] -== Analogia com um Adaptador de Tomada - -== ! - -image::patterns/estruturais/adapter-analogia-tomada.png[] - -[transition=zoom] -== Exemplo: Modelagem fictícia de adaptadores para sistemas de pagamento online - -== ! -image::patterns/estruturais/sistemas-pagamento-adapters.png[] - -[transition=zoom] -== Geração de números verdadeiramente aleatórios - -- Implementação de adapters para serviços web como http://random.org e http://random.irb.hr - -[transition=zoom, background-opacity=0.4] -== Princípios utilizados - -[%step] -- https://en.wikipedia.org/wiki/Single_responsibility_principle[Single Responsibility Principle (SRP)] -- https://en.wikipedia.org/wiki/Open–closed_principle[Open/Closed Principle (OCP)] - -[transition=zoom] -== ! - -Liskov Substitution Principle (LSP) image:patterns/estruturais/adapter-analogia-varios.png[] - -[background-opacity=0.4] -== Princípios utilizados - -[%step] -- https://en.wikipedia.org/wiki/Dependency_inversion_principle[Dependency Inversion Principle (DIP)] -- https://tuhrig.de/programming-to-an-interface/[Programar para uma interface não uma implementação] (GoF) - -image::recommendations.jpg[background, size=contain, text=https://www.smart-energy.com, link=https://www.smart-energy.com/industry-sectors/smart-energy/five-key-recommendations-for-the-sustainable-energy-sector-growth-in-mena/] - - -[transition=zoom] -== Porque não adere ao Interface Segregation Principle (ISP)? Vamos rever a modelagem... - -== ! - -image::patterns/estruturais/adapter.png[background, size=contain] - -== Onde o padrão é usado no JDK - -Adapters não explícitos implementados como métodos: - -[%step] -- `java.util.Arrays#asList()`: retorna uma nova instância de um adaptador de array para List. -- `java.util.Collections#list()`: returna uma nova instância de um adaptador de coleção (conjuntos: Set, filas: Queue, etc), para List. - -== Onde o padrão é usado em outros lugares - -[%step] -- Geração de logs é exemplo onde o Adapter e outros padrões (como o Facade) são usados. -- https://logging.apache.org/log4j/log4j-2.7/log4j-jul/index.html[Apache Log4J JUL Adapter]: usar https://logging.apache.org/log4j/[Apache Log4J] como um adaptador para java.util.logging (JUL). - -=== Pensando em interfaces como adaptadores - -[%step] -- Em um classe que implementa múltiplas interfaces, podemos imaginá-la como sendo um adaptador para todas estas interfaces. -- Java Collections Framework (JCF) - classes como ArrayList e LinkedList funcionam como adaptadores para a interface List. -- Internamente, estas classes podem ter métodos com nomes e assinaturas diferentes -- ArrayList utiliza `elementData(index)` para acessar um elemento. LinkedList utiliza-se `node(index).item`. - -=== Pensando em interfaces como adaptadores - -[%step] -- O método `public E get(int index)` de `List` padroniza o acesso aos elementos. -- ArrayList e LinkedList implementam múltiplas interfaces: List -> Collection -> Iterable. -- Tal hierarquia nos permite usar um ArrayList como se fosse um objeto List, Collection ou Iterable. - -[transition=fade] -== Material e Projetos no GitHub - -- https://git.io/JJKLy -- Exercícios em Java na página do link acima. diff --git a/estruturais/01-adapter/slides.html b/estruturais/01-adapter/slides.html new file mode 100644 index 000000000..97d38e55a --- /dev/null +++ b/estruturais/01-adapter/slides.html @@ -0,0 +1,958 @@ + + + + + + + +Padrão de Projetos Adapter + + + + + + +
+
+
+
+

Prof. Manoel Campos

+
+
+
+biolink +
+
+
+
+
+

1. Categoria

+
+
+

Padrão de projeto estrutural building structure

+
+
+
+
+

2. Definição

+
+
+

📘"O padrão adapter converte a interface de uma classe em outra interface que os clientes esperam. Um adaptador permite que classes anteriormente incompatíveis possam trabalhar em conjunto". [UCPP]

+
+
+

ucpp

+
+
+
+
+

3. Aplicabilidade

+
+
+

Quando:

+
+
+
    +
  • +

    utiliza-se um determinado serviço web, framework ou biblioteca (componente) onde existem implementações incompatíveis destes e deseja-se ser capaz de trocar um componente por outro;

    +
  • +
  • +

    integração de componentes existentes com sistemas de outras empresas. Exemplos incluem sistemas de pagamento como PagSeguro e PayPal.

    +
  • +
+
+
+
+
+

4. Modelagem do Adapter

+
+ +
+
+
+

5. !

+
+
+
+background +
+
+
+
+
+

6. Analogia com um Adaptador de Tomada

+
+ +
+
+
+

7. !

+
+
+
+adapter analogia tomada +
+
+
+
+
+

8. Exemplo: Modelagem fictícia de adaptadores para sistemas de pagamento online

+
+ +
+
+
+

9. !

+
+
+
+sistemas pagamento adapters +
+
+
+
+
+

10. Geração de números verdadeiramente aleatórios

+
+
+ +
+
+
+
+

11. Princípios utilizados

+ +
+
+

12. !

+
+
+

Liskov Substitution Principle (LSP) adapter analogia varios

+
+
+
+
+

13. Princípios utilizados

+ +
+
+

14. Porque não adere ao Interface Segregation Principle (ISP)? Vamos rever a modelagem…​

+
+ +
+
+
+

15. !

+
+
+
+background +
+
+
+
+
+

16. Onde o padrão é usado no JDK

+
+
+

Adapters não explícitos implementados como métodos:

+
+
+
    +
  • +

    java.util.Arrays#asList(): retorna uma nova instância de um adaptador de array para List.

    +
  • +
  • +

    java.util.Collections#list(): returna uma nova instância de um adaptador de coleção (conjuntos: Set, filas: Queue, etc), para List.

    +
  • +
+
+
+
+
+

17. Onde o padrão é usado em outros lugares

+
+
+
    +
  • +

    Geração de logs é exemplo onde o Adapter e outros padrões (como o Facade) são usados.

    +
  • +
  • +

    Apache Log4J JUL Adapter: usar Apache Log4J como um adaptador para java.util.logging (JUL).

    +
  • +
+
+
+

17.1. Pensando em interfaces como adaptadores

+
+
    +
  • +

    Em um classe que implementa múltiplas interfaces, podemos imaginá-la como sendo um adaptador para todas estas interfaces.

    +
  • +
  • +

    Java Collections Framework (JCF) - classes como ArrayList e LinkedList funcionam como adaptadores para a interface List.

    +
  • +
  • +

    Internamente, estas classes podem ter métodos com nomes e assinaturas diferentes

    +
  • +
  • +

    ArrayList utiliza elementData(index) para acessar um elemento. LinkedList utiliza-se node(index).item.

    +
  • +
+
+
+
+

17.2. Pensando em interfaces como adaptadores

+
+
    +
  • +

    O método public E get(int index) de List padroniza o acesso aos elementos.

    +
  • +
  • +

    ArrayList e LinkedList implementam múltiplas interfaces: List → Collection → Iterable.

    +
  • +
  • +

    Tal hierarquia nos permite usar um ArrayList como se fosse um objeto List, Collection ou Iterable.

    +
  • +
+
+
+
+
+
+

18. Material e Projetos no GitHub

+
+
+ +
+
+
+
+ + + + + \ No newline at end of file diff --git a/estruturais/README.adoc b/estruturais/README.adoc deleted file mode 100644 index 0ad76c2d1..000000000 --- a/estruturais/README.adoc +++ /dev/null @@ -1,22 +0,0 @@ -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font -:imagesdir: ../images/ - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Estruturais - -image::building-structure.jpg[width=300] - -- link:01-adapter[Adapter] - -ifndef::env-github[image:back.png[alt=Voltar, link=../]] diff --git a/estruturais/README.html b/estruturais/README.html new file mode 100644 index 000000000..5b5e03896 --- /dev/null +++ b/estruturais/README.html @@ -0,0 +1,473 @@ + + + + + + + +Padrões de Projetos Estruturais + + + + + + + +
+
+
+building structure +
+
+
+ +
+
+

Voltar

+
+
+ + + + + \ No newline at end of file diff --git a/estruturais/decorator/README.adoc b/estruturais/decorator/README.adoc deleted file mode 100755 index 0d4b23f05..000000000 --- a/estruturais/decorator/README.adoc +++ /dev/null @@ -1,74 +0,0 @@ -:imagesdir: ../../images/patterns/estruturais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Estruturais - -== Decorator (Decorador) - -- http://www.javabyexamples.com/decorator-pattern-with-lombok - -image:decorator-analogy.jpg[] - -=== Definição - - -=== Aplicabilidade - - -=== Modelagem do Padrão - -.Figura 1: Modelagem do padrão Decorator -image::decorator.png[] - - -=== Princípios utilizados - -- - -=== Exemplos - -- https://refactoring.guru/design-patterns/decorator[Envio de múltiplas notificações] - - -== Padrões Relacionados - -- Adapter - -== Onde o padrão é usado no JDK e outras bibliotecas - -Utilizado para a manipulação de Streams para entrada e saída de dados (como leitura e gravação de arquivos), -em classes como: - -- InputStream, InputStreamReader, BufferedReader para leitura de dados -- OutputStream, OutputStreamWriter, BufferedWritter para gravação de dados. - -Cada uma das classes nestes conjuntos apresentados permitem ler/gravar dados em formato de bytes, caracteres ou String. -Dependendo da sua necessidade, você pode escolher quais objetos instanciar, para obter a funcionalidade que deseja por meio -de composição. - -IMPORTANT: Não confundir tais Streams com o recurso de processamento de dados incluído no Java 8, que possui o mesmo nome. - -=== Prós e Contras - -A linguagem Java é conhecida por ser verbosa, ou seja, requerer muito código para algo simples. -Um exemplo clássico disto é a manipulação de arquivos com os objetos Stream, mencionados anteriormente. -Apesar da quantidade de código necessária, Java permite trabalhar com uma infinidade de dispositivos -de entrada e saída por meio da mesma interface. Isto inclui arquivos, sockets para comunicação de rede, -o terminal (console). - -Felizmente, no Java 8+, alguns recursos foram adicionados para tornar mais direta a utilização de -tais objetos que implementam o padrão Decorator, por meio de métodos como `Files.newBufferedReader()`. - -== Exercícios diff --git a/estruturais/decorator/README.html b/estruturais/decorator/README.html new file mode 100644 index 000000000..6f820297e --- /dev/null +++ b/estruturais/decorator/README.html @@ -0,0 +1,574 @@ + + + + + + + +Padrões de Projetos Estruturais + + + + + + + +
+
+

1. Decorator (Decorador)

+
+ +
+

decorator analogy

+
+
+

1.1. Definição

+ +
+
+

1.2. Aplicabilidade

+ +
+
+

1.3. Modelagem do Padrão

+
+
+decorator +
+
Figure 1. Figura 1: Modelagem do padrão Decorator
+
+
+
+

1.4. Princípios utilizados

+
+

-

+
+
+
+

1.5. Exemplos

+ +
+
+
+
+

2. Padrões Relacionados

+
+
+
    +
  • +

    Adapter

    +
  • +
+
+
+
+
+

3. Onde o padrão é usado no JDK e outras bibliotecas

+
+
+

Utilizado para a manipulação de Streams para entrada e saída de dados (como leitura e gravação de arquivos), +em classes como:

+
+
+
    +
  • +

    InputStream, InputStreamReader, BufferedReader para leitura de dados

    +
  • +
  • +

    OutputStream, OutputStreamWriter, BufferedWritter para gravação de dados.

    +
  • +
+
+
+

Cada uma das classes nestes conjuntos apresentados permitem ler/gravar dados em formato de bytes, caracteres ou String. +Dependendo da sua necessidade, você pode escolher quais objetos instanciar, para obter a funcionalidade que deseja por meio +de composição.

+
+
+ + + + + +
+ + +Não confundir tais Streams com o recurso de processamento de dados incluído no Java 8, que possui o mesmo nome. +
+
+
+

3.1. Prós e Contras

+
+

A linguagem Java é conhecida por ser verbosa, ou seja, requerer muito código para algo simples. +Um exemplo clássico disto é a manipulação de arquivos com os objetos Stream, mencionados anteriormente. +Apesar da quantidade de código necessária, Java permite trabalhar com uma infinidade de dispositivos +de entrada e saída por meio da mesma interface. Isto inclui arquivos, sockets para comunicação de rede, +o terminal (console).

+
+
+

Felizmente, no Java 8+, alguns recursos foram adicionados para tornar mais direta a utilização de +tais objetos que implementam o padrão Decorator, por meio de métodos como Files.newBufferedReader().

+
+
+
+
+
+

4. Exercícios

+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/estruturais/decorator/index.html b/estruturais/decorator/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/decorator/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/facade/README.adoc b/estruturais/facade/README.adoc deleted file mode 100644 index bfba033a1..000000000 --- a/estruturais/facade/README.adoc +++ /dev/null @@ -1,47 +0,0 @@ -:imagesdir: ../../images/patterns/estruturais -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Padrões de Projetos Estruturais - -== Facade (Fachada) - - - -=== Definição - - -=== Aplicabilidade - - -=== Modelagem do Padrão - - -=== Exemplos Práticos - - -=== Princípios utilizados - - -== Padrões Relacionados - -- Adapter - - -== Exercícios - -=== Cotações de Empresas da Bolsa de Valores - -Veja o projeto base e informações em link:cotacao-bolsa-valores[cotacao-bolsa-valores]. - diff --git a/estruturais/facade/README.html b/estruturais/facade/README.html new file mode 100644 index 000000000..619d3c3fa --- /dev/null +++ b/estruturais/facade/README.html @@ -0,0 +1,506 @@ + + + + + + + +Padrões de Projetos Estruturais + + + + + + + +
+
+

1. Facade (Fachada)

+
+
+

1.1. Definição

+ +
+
+

1.2. Aplicabilidade

+ +
+
+

1.3. Modelagem do Padrão

+ +
+
+

1.4. Exemplos Práticos

+ +
+
+

1.5. Princípios utilizados

+ +
+
+
+
+

2. Padrões Relacionados

+
+
+
    +
  • +

    Adapter

    +
  • +
+
+
+
+
+

3. Exercícios

+
+
+

3.1. Cotações de Empresas da Bolsa de Valores

+
+

Veja o projeto base e informações em cotacao-bolsa-valores.

+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/estruturais/facade/cotacao-bolsa-valores/README.adoc b/estruturais/facade/cotacao-bolsa-valores/README.adoc deleted file mode 100644 index c6fb6da79..000000000 --- a/estruturais/facade/cotacao-bolsa-valores/README.adoc +++ /dev/null @@ -1,30 +0,0 @@ -:source-highlighter: highlightjs -:numbered: -:unsafe: -:icons: font - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Projeto Base que obtem a cotação de empresas da bolsa de valores (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/estruturais/facade/cotacao-bolsa-valores[zip]) - -O projeto utiliza 3 serviços diferentes (Yahoo Finance, AlphaVantage e Quandl) para obter a cotação de empresas da bolsa de valores. -São utilizadas bibliotecas existentes para fazer acesso a estes serviços -e o código disponibilizado mostra como usar cada uma destas bibliotecas. - -Mas como observará, a forma de utilizar cada uma é totalmente diferente da outra. -A partir deste código, altere o projeto criando 3 fachadas: um pra cada uma -das bibliotecas dos serviços mencionados. -Com isto, será possível trocar um serviço pelo outro sem alterar o código do projeto. - -Adicionalmente, você perceberá que o código das empresas tem formato diferente em cada serviço. -Como os fachadas poderiam padronizar estes códigos e tornar o formato igual para todos os serviços? - -No projeto disponibilizado, a classe `Principal` é na nossa classe `Cliente`: é ela quem usa as fachadas. -Analisando o novo código da classe principal, que outro padrão poderíamos aplicar em seguida? diff --git a/estruturais/facade/cotacao-bolsa-valores/README.html b/estruturais/facade/cotacao-bolsa-valores/README.html new file mode 100644 index 000000000..fd950d634 --- /dev/null +++ b/estruturais/facade/cotacao-bolsa-valores/README.html @@ -0,0 +1,477 @@ + + + + + + + +Projeto Base que obtem a cotação de empresas da bolsa de valores (zip) + + + + + + + +
+
+

O projeto utiliza 3 serviços diferentes (Yahoo Finance, AlphaVantage e Quandl) para obter a cotação de empresas da bolsa de valores. +São utilizadas bibliotecas existentes para fazer acesso a estes serviços +e o código disponibilizado mostra como usar cada uma destas bibliotecas.

+
+
+

Mas como observará, a forma de utilizar cada uma é totalmente diferente da outra. +A partir deste código, altere o projeto criando 3 fachadas: um pra cada uma +das bibliotecas dos serviços mencionados. +Com isto, será possível trocar um serviço pelo outro sem alterar o código do projeto.

+
+
+

Adicionalmente, você perceberá que o código das empresas tem formato diferente em cada serviço. +Como os fachadas poderiam padronizar estes códigos e tornar o formato igual para todos os serviços?

+
+
+

No projeto disponibilizado, a classe Principal é na nossa classe Cliente: é ela quem usa as fachadas. +Analisando o novo código da classe principal, que outro padrão poderíamos aplicar em seguida?

+
+
+ + + + + \ No newline at end of file diff --git a/estruturais/facade/cotacao-bolsa-valores/index.html b/estruturais/facade/cotacao-bolsa-valores/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/facade/cotacao-bolsa-valores/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/facade/index.html b/estruturais/facade/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/facade/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/estruturais/index.html b/estruturais/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/estruturais/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/exercicios/README.adoc b/exercicios/README.adoc deleted file mode 100755 index 163044f41..000000000 --- a/exercicios/README.adoc +++ /dev/null @@ -1,25 +0,0 @@ -:source-highlighter: highlightjs -:numbered: -:unsafe: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Código base para resolver exercícios propostos de Padrões de Projetos (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/exercicios[zip]) - -Os projetos a seguir estão incompletos. Acesse a página de cada um e leia as informações -disponibilizadas. Em seguida, implemente uma solução com padrões de projetos -a partir do código inicial fornecido. - -- link:calculo-desconto[Cálculo de Desconto] -- link:instanciar-produtos[Instanciando Produtos] -- link:envio-mensagens[Envio de Mensagens por diferentes canais] -- link:imposto-renda[Cálculo de Imposto de Renda para Pessoa Física e Jurídica] -- link:random-numbers[Bibliotecas para geração de números pseudo-aleatórios] -- link:real-random-number-services[Serviços para geração de números realmente aleatórios] diff --git a/exercicios/README.html b/exercicios/README.html new file mode 100644 index 000000000..dc3b0ad59 --- /dev/null +++ b/exercicios/README.html @@ -0,0 +1,484 @@ + + + + + + + +Código base para resolver exercícios propostos de Padrões de Projetos (zip) + + + + + + +
+
+

Os projetos a seguir estão incompletos. Acesse a página de cada um e leia as informações +disponibilizadas. Em seguida, implemente uma solução com padrões de projetos +a partir do código inicial fornecido.

+
+ +
+ + + + + \ No newline at end of file diff --git a/exercicios/calculo-desconto/README.adoc b/exercicios/calculo-desconto/README.adoc deleted file mode 100755 index 98fd9a41f..000000000 --- a/exercicios/calculo-desconto/README.adoc +++ /dev/null @@ -1,30 +0,0 @@ -:source-highlighter: highlightjs -:unsafe: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Cálculo de Descontos - -Considere que temos um sistema de vendas onde diferentes formas de desconto podem ser implementadas de acordo com as promoções vigentes, como em datas comemorativas. O sistema deve permitir o cálculo do desconto sobre a venda das seguintes maneiras: - -- percentual de desconto definido (que pode vir de um banco de dados); -- percentual de desconto progressivo: `valor da compra/25`, não podendo ultrapassar 20% (este são apenas valores arbitrários de exemplo); -- desconto de 15% na data de aniversário do cliente. - -O usuário é quem escolhe o tipo de desconto a ser aplicado, não o programa. -O programa deve apenas permitir que seja mudado o algoritmo de cálculo do desconto. - -== Responda - -1. Qual padrão de projeto pode ser utilizado no desenvolvimento de uma solução? -2. Como poderíamos implementar estes tipos de desconto sem utilizar Padrões de Projetos? -3. Quais os problemas que tal implementação traria? -4. Implemente o projeto e envie o link para repositório no GitHub, onde o README deve conter as respostas. - diff --git a/exercicios/calculo-desconto/README.html b/exercicios/calculo-desconto/README.html new file mode 100644 index 000000000..cc4eee719 --- /dev/null +++ b/exercicios/calculo-desconto/README.html @@ -0,0 +1,502 @@ + + + + + + + +Cálculo de Descontos + + + + + + +
+
+
+
+

Considere que temos um sistema de vendas onde diferentes formas de desconto podem ser implementadas de acordo com as promoções vigentes, como em datas comemorativas. O sistema deve permitir o cálculo do desconto sobre a venda das seguintes maneiras:

+
+
+
    +
  • +

    percentual de desconto definido (que pode vir de um banco de dados);

    +
  • +
  • +

    percentual de desconto progressivo: valor da compra/25, não podendo ultrapassar 20% (este são apenas valores arbitrários de exemplo);

    +
  • +
  • +

    desconto de 15% na data de aniversário do cliente.

    +
  • +
+
+
+

O usuário é quem escolhe o tipo de desconto a ser aplicado, não o programa. +O programa deve apenas permitir que seja mudado o algoritmo de cálculo do desconto.

+
+
+
+
+

Responda

+
+
+
    +
  1. +

    Qual padrão de projeto pode ser utilizado no desenvolvimento de uma solução?

    +
  2. +
  3. +

    Como poderíamos implementar estes tipos de desconto sem utilizar Padrões de Projetos?

    +
  4. +
  5. +

    Quais os problemas que tal implementação traria?

    +
  6. +
  7. +

    Implemente o projeto e envie o link para repositório no GitHub, onde o README deve conter as respostas.

    +
  8. +
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/exercicios/calculo-desconto/index.html b/exercicios/calculo-desconto/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/exercicios/calculo-desconto/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/exercicios/envio-mensagens/README.adoc b/exercicios/envio-mensagens/README.adoc deleted file mode 100755 index cff315a75..000000000 --- a/exercicios/envio-mensagens/README.adoc +++ /dev/null @@ -1,32 +0,0 @@ -:source-highlighter: highlightjs -:unsafe: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Envio de Mensagens - -Atualmente, aplicações de diversas plataformas como web e mobile possuem recursos de envio de mensagens por diferentes meios como: email, sms, WhatsApp, notificações push, etc. - -Considere você precisará: - -- trocar a forma de envio de mensagens por outra; -- ou alternar entre diferentes formas. - -No entanto, você não quer ficar escrevendo `if()` em todos os locais onde precisa definir qual classe será instanciada para enviar mensagens e quer que o processo de decisão de qual classe instanciar (que define a forma de envio de mensagens) seja encapsulado. - -Faça as alterações necessárias no projeto atual e implemente um padrão para resolver os problemas mencionados. - -> O projeto requer JDK 11 ou superior. - -== Responda - -1. Qual padrão de projeto pode ser utilizado para resolver este problema? Implemente a solução (não precisa enviar mensagens de fato, apenas simular com prints). - -Implemente o projeto e envie link para repositório no GitHub, onde o README deve conter as respostas. diff --git a/exercicios/envio-mensagens/README.html b/exercicios/envio-mensagens/README.html new file mode 100644 index 000000000..737fd8f6a --- /dev/null +++ b/exercicios/envio-mensagens/README.html @@ -0,0 +1,505 @@ + + + + + + + +Envio de Mensagens + + + + + + +
+
+
+
+

Atualmente, aplicações de diversas plataformas como web e mobile possuem recursos de envio de mensagens por diferentes meios como: email, sms, WhatsApp, notificações push, etc.

+
+
+

Considere você precisará:

+
+
+
    +
  • +

    trocar a forma de envio de mensagens por outra;

    +
  • +
  • +

    ou alternar entre diferentes formas.

    +
  • +
+
+
+

No entanto, você não quer ficar escrevendo if() em todos os locais onde precisa definir qual classe será instanciada para enviar mensagens e quer que o processo de decisão de qual classe instanciar (que define a forma de envio de mensagens) seja encapsulado.

+
+
+

Faça as alterações necessárias no projeto atual e implemente um padrão para resolver os problemas mencionados.

+
+
+
+
+

O projeto requer JDK 11 ou superior.

+
+
+
+
+
+
+

Responda

+
+
+
    +
  1. +

    Qual padrão de projeto pode ser utilizado para resolver este problema? Implemente a solução (não precisa enviar mensagens de fato, apenas simular com prints).

    +
  2. +
+
+
+

Implemente o projeto e envie link para repositório no GitHub, onde o README deve conter as respostas.

+
+
+
+
+ + + + + \ No newline at end of file diff --git a/exercicios/envio-mensagens/index.html b/exercicios/envio-mensagens/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/exercicios/envio-mensagens/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/exercicios/imposto-renda/README.adoc b/exercicios/imposto-renda/README.adoc deleted file mode 100755 index f715a8d99..000000000 --- a/exercicios/imposto-renda/README.adoc +++ /dev/null @@ -1,47 +0,0 @@ -:source-highlighter: highlightjs -:unsafe: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Cálculo de Imposto de Renda (https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/exercicios/imposto-renda[zip]) - -Considere um sistema de recursos humanos que possui uma hierarquia de classes de Pessoa, PessoaFisica (PF) e PessoaJuridica (PJ), sendo a 1ª a superclasse das 2 últimas. - -O cálculo do imposto de renda (IR) para PF é diferente para PJ. Por simplificação, vamos considerar que PFs pagam 11% de `alíquota de IRPF`, seguindo a fórmula: - -``` -IR Parcial = (Salário bruto - dedução em R$ por dependente - R$ INSS) * alíquota IRPF -IR da PF (R$) = IR Parcial - (gastos saúde + gastos educação) -``` - -No caso de PJ existem diferentes cálculos. Vamos considerar apenas o cálculo para empresas que aderem ao regime tributário chamado "Lucro Real". Neste caso, elas pagam 15% de `alíquota de IRPJ` sobre o lucro da companhia. Caso a empresa exceda R$ 20 mil por mês na cobrança de IR, ela também paga 10% sobre o valor que exceder, ou seja: - -``` -Limite Cobrança IR (R$) = 20000 -IR Parcial (R$) = lucro * alíquota IRPJ -// Total de IR a pagar que excede o limite indicado acima -IR Excedente (R$) = IR Parcial - Limite Cobrança IR -Aliquota Adicional = 0.1 // 10% -IR da PJ (R$) = IR Parcial + (IR Excedente > 0 ? IR Excedente * Aliquota Adicional : 0) -``` - -A PF física paga INSS. Por simplificação, vamos considerar que são 11% sobre o salário bruto (com a reforma da previdência, existe uma ampla faixa de alíquotas). - -A PJ paga INSS para seus funcionários, mas não vamos considerar isto aqui. Considere a Contribuição Social sobre Lucro Líquido (CSLL) que, de forma simplificada, aqui consideraremos 9% do lucro. - -Adicionalmente, a PJ paga ICMS por produtos adquiridos. Vamos considerar que a alíquota é de 5%. - -Resumindo: - -- a PF paga IR + INSS -- a PJ paga IR + CSLL + ICMS - -Precisamos de um método que calcule o valor em R$ de todos os impostos pagos por PFs e PJs. -Considerando que deve-se garantir que o cálculo inclua o valor do IR, que padrão de projeto pode ser aplicado para isto? diff --git a/exercicios/imposto-renda/README.html b/exercicios/imposto-renda/README.html new file mode 100644 index 000000000..b51253da6 --- /dev/null +++ b/exercicios/imposto-renda/README.html @@ -0,0 +1,508 @@ + + + + + + + +Cálculo de Imposto de Renda (zip) + + + + + + +
+
+

Considere um sistema de recursos humanos que possui uma hierarquia de classes de Pessoa, PessoaFisica (PF) e PessoaJuridica (PJ), sendo a 1ª a superclasse das 2 últimas.

+
+
+

O cálculo do imposto de renda (IR) para PF é diferente para PJ. Por simplificação, vamos considerar que PFs pagam 11% de alíquota de IRPF, seguindo a fórmula:

+
+
+
+
IR Parcial = (Salário bruto - dedução em R$ por dependente - R$ INSS) * alíquota IRPF
+IR da PF (R$) = IR Parcial - (gastos saúde + gastos educação)
+
+
+
+

No caso de PJ existem diferentes cálculos. Vamos considerar apenas o cálculo para empresas que aderem ao regime tributário chamado "Lucro Real". Neste caso, elas pagam 15% de alíquota de IRPJ sobre o lucro da companhia. Caso a empresa exceda R$ 20 mil por mês na cobrança de IR, ela também paga 10% sobre o valor que exceder, ou seja:

+
+
+
+
Limite Cobrança IR (R$) = 20000
+IR Parcial (R$) = lucro * alíquota IRPJ
+// Total de IR a pagar que excede o limite indicado acima
+IR Excedente (R$) = IR Parcial - Limite Cobrança IR
+Aliquota Adicional = 0.1 // 10%
+IR da PJ (R$) = IR Parcial + (IR Excedente > 0 ? IR Excedente * Aliquota Adicional  : 0)
+
+
+
+

A PF física paga INSS. Por simplificação, vamos considerar que são 11% sobre o salário bruto (com a reforma da previdência, existe uma ampla faixa de alíquotas).

+
+
+

A PJ paga INSS para seus funcionários, mas não vamos considerar isto aqui. Considere a Contribuição Social sobre Lucro Líquido (CSLL) que, de forma simplificada, aqui consideraremos 9% do lucro.

+
+
+

Adicionalmente, a PJ paga ICMS por produtos adquiridos. Vamos considerar que a alíquota é de 5%.

+
+
+

Resumindo:

+
+
+
    +
  • +

    a PF paga IR + INSS

    +
  • +
  • +

    a PJ paga IR + CSLL + ICMS

    +
  • +
+
+
+

Precisamos de um método que calcule o valor em R$ de todos os impostos pagos por PFs e PJs. +Considerando que deve-se garantir que o cálculo inclua o valor do IR, que padrão de projeto pode ser aplicado para isto?

+
+
+ + + + + \ No newline at end of file diff --git a/exercicios/imposto-renda/index.html b/exercicios/imposto-renda/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/exercicios/imposto-renda/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/exercicios/index.html b/exercicios/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/exercicios/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/exercicios/instanciar-produtos/README.adoc b/exercicios/instanciar-produtos/README.adoc deleted file mode 100755 index e41acc3bc..000000000 --- a/exercicios/instanciar-produtos/README.adoc +++ /dev/null @@ -1,45 +0,0 @@ -:source-highlighter: highlightjs -:unsafe: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Instanciando Produtos - -Considere que temos uma classe Produto com os seguintes atributos: - -- **long id** -- String codigoEan //código de barras -- **String descricao** -- **String marca** -- String modelo -- **double preco** -- **LocalDate dataCadastro** -- LocalDate dataUltimaAtualizacao -- int estoque -- **String categoria** -- String urlFoto - -A classe possui os seguintes requisitos: - -1. Os atributos em negrito são obrigatórios. -2. Não pode ser informado um modelo se não for informada a marca. -3. O preço deve ser maior que zero. -4. A data de cadastro não pode ser alterada e deve ser definida por padrão com a data atual. -5. A data da última atualização não pode ser anterior a data de cadastro. -6. O estoque padrão deve ser zero e não pode ser atribuído valor negativo. -7. Nenhum dos atributos String pode ser null. - -== Responda - -1. Que padrão de projeto pode ser utilizado para tornar mais fácil e claro o processo de instanciação de tal classe, uma vez que há dependências entre diferentes atributos, atributos obrigatórios e outros não? Implemente tal padrão para esta classe. - -Implemente o projeto e envie link para repositório no GitHub, onde o README deve conter as respostas. - - diff --git a/exercicios/instanciar-produtos/README.html b/exercicios/instanciar-produtos/README.html new file mode 100644 index 000000000..813f0e0de --- /dev/null +++ b/exercicios/instanciar-produtos/README.html @@ -0,0 +1,544 @@ + + + + + + + +Instanciando Produtos + + + + + + +
+
+
+
+

Considere que temos uma classe Produto com os seguintes atributos:

+
+
+
    +
  • +

    long id

    +
  • +
  • +

    String codigoEan //código de barras

    +
  • +
  • +

    String descricao

    +
  • +
  • +

    String marca

    +
  • +
  • +

    String modelo

    +
  • +
  • +

    double preco

    +
  • +
  • +

    LocalDate dataCadastro

    +
  • +
  • +

    LocalDate dataUltimaAtualizacao

    +
  • +
  • +

    int estoque

    +
  • +
  • +

    String categoria

    +
  • +
  • +

    String urlFoto

    +
  • +
+
+
+

A classe possui os seguintes requisitos:

+
+
+
    +
  1. +

    Os atributos em negrito são obrigatórios.

    +
  2. +
  3. +

    Não pode ser informado um modelo se não for informada a marca.

    +
  4. +
  5. +

    O preço deve ser maior que zero.

    +
  6. +
  7. +

    A data de cadastro não pode ser alterada e deve ser definida por padrão com a data atual.

    +
  8. +
  9. +

    A data da última atualização não pode ser anterior a data de cadastro.

    +
  10. +
  11. +

    O estoque padrão deve ser zero e não pode ser atribuído valor negativo.

    +
  12. +
  13. +

    Nenhum dos atributos String pode ser null.

    +
  14. +
+
+
+
+
+

Responda

+
+
+
    +
  1. +

    Que padrão de projeto pode ser utilizado para tornar mais fácil e claro o processo de instanciação de tal classe, uma vez que há dependências entre diferentes atributos, atributos obrigatórios e outros não? Implemente tal padrão para esta classe.

    +
  2. +
+
+
+

Implemente o projeto e envie link para repositório no GitHub, onde o README deve conter as respostas.

+
+
+
+
+ + + + + \ No newline at end of file diff --git a/exercicios/instanciar-produtos/index.html b/exercicios/instanciar-produtos/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/exercicios/instanciar-produtos/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/exercicios/random-numbers/README.adoc b/exercicios/random-numbers/README.adoc deleted file mode 100755 index ab0bbfbc6..000000000 --- a/exercicios/random-numbers/README.adoc +++ /dev/null @@ -1,62 +0,0 @@ -:source-highlighter: highlightjs -:numbered: -:unsafe: - -ifdef::env-github[] -:outfilesuffix: .adoc -:caution-caption: :fire: -:important-caption: :exclamation: -:note-caption: :paperclip: -:tip-caption: :bulb: -:warning-caption: :warning: -endif::[] - -= Geradores de Números Aleatórios (link:https://kinolien.github.io/gitzip/?download=/manoelcampos/padroes-projetos/tree/master/exercicios/random-numbers[zip]) - -Em qualquer linguagem de programação existem geradores de números pseudo-aleatórios. Estes geradores são chamados assim pois os números não são de fato aleatórios, uma vez que é utilizada uma equação para calcular cada número gerado. Em Java, a classe `Random` do pacote `java.util` é uma das formas utilizadas para gerar tais números. No entanto, existem diferentes implementações destes geradores, cada uma com finalidades específicas ou diferentes níveis de qualidades em relação à aleatoriedade dos números gerados. - -Bibliotecas como a Apache Commons Math fornecem, dentre outras funcionalidades, diversos geradores de números pseudo-aleatórios. - -== O problema - -Existe uma grande variedade de implementações de tais geradores, cada implementação fornecendo uma interface diferente da outra. -Para este projeto, observe o diagrama de classes abaixo. - -image:random-numbers.png[] - -Ele apresenta alguns métodos da classe `Random` do pacote `java.util` e da interface `RealDistribution` da biblioteca Apache Commons Math. Algumas das classes que implementam esta última interface são `NormalDistribution` e `LogNormalDistribution`. Como podem ver, existem diferenças entre as classes/interfaces, tornando também diferente a forma de utilizar cada uma das implementações disponíveis. - -A seguir são apresentados os detalhes das diferentes implementações. - -=== Classe Random da plataforma Java - -Na classe `Random` temos os métodos `nextDouble()` e `doubles(long streamSize)`. Os dois podem ser utilizados para gerar números aleatórios. O primeiro gera um único número a cada vez que for chamado. O segundo gera um conjunto de números, cuja quantidade é definida pelo parâmetro `streamSize`. Assim, chamando `doubles(3)`, serão gerados 3 números aleatórios. - -Adicionalmente, esta classe possui 2 construtores: um que não recebe parâmetro algum e outro que recebe uma `seed`. A `seed` (semente) é apenas um número que define o valor inicial do gerador. Se instanciarmos um gerador com a mesma `seed`, a sequência de números gerados será sempre a mesma. Se alterarmos a `seed` ou não informarmos uma, a cada vez que executarmos a aplicação, a sequência de números gerados será diferente. - -=== Biblioteca Apache Commons Math - -Já nas classes que implementam a interface `RealDistribution` da biblioteca Apache Commons Math (como `NormalDistribution` e `LogNormalDistribution`), os métodos que retornam um número aleatório ou um conjunto de números são diferentes. Temos os métodos `sample()` e `sample(int sampleSize)`, semelhantes aos métodos da classe `Random`, mas com nomes, tipos de parâmetro e retorno diferentes. - -Por fim, nestas classes, se for preciso definir uma seed, isto não é feito por meio de um construtor, mas chamando o método `reseedRandomGenerator(long seed)`. - -== O Desafio - -Identifique qual padrão de projeto pode ser aplicado para uniformizar a interface das classes `Random` do pacote `java.util` e das classes que implementam a interface `RealDistribution` da biblioteca Apache Commons Math. O padrão deve então permitir que a forma de utilizar qualquer destas classes seja a mesma. - -Altere a aplicação de exemplo nesta pasta (que já inclui a dependência para a biblioteca Apache Commons Math no arquivo link:pom.xml[pom.xml]) para aplicar o padrão de projeto adequado. Por fim, modifique a classe `Principal` para utilizar as classes criadas para o padrão. - -== Detalhes de Implementação - -Observe que os métodos `sample(int sampleSize)` da interface `RealDistribution` e `doubles(long streamSize)` da classe `Random` tem tipos de parâmetros e retorno diferentes. O primeiro retorna um vetor de double e o segundo retorna um objeto `DoubleStream`. -Uma maneira de uniformizar tais métodos é fazer com que o segundo também retorne um vetor de double. O código para isto pode ser: - -[source,java] ----- -double[] numeros = random.doubles(10).toArray(); ----- - -Neste exemplo, estamos chamando o método `doubles()`, indicando que desejamos gerar 10 números aleatórios e convertendo de `DoubleStream` para um vetor usando o método `toArray()`. - -Estamos padronizando fazendo os métodos retornarem vetores, pelo fato destes serem mais familiares que Streams (como é o caso do DoubleStream). -Streams são mais modernos, seguros e flexíveis que vetores, mas vamos utilizar apenas vetores para simplificar. diff --git a/exercicios/random-numbers/README.html b/exercicios/random-numbers/README.html new file mode 100644 index 000000000..a3ee9987e --- /dev/null +++ b/exercicios/random-numbers/README.html @@ -0,0 +1,535 @@ + + + + + + + +Geradores de Números Aleatórios (zip) + + + + + + +
+
+
+
+

Em qualquer linguagem de programação existem geradores de números pseudo-aleatórios. Estes geradores são chamados assim pois os números não são de fato aleatórios, uma vez que é utilizada uma equação para calcular cada número gerado. Em Java, a classe Random do pacote java.util é uma das formas utilizadas para gerar tais números. No entanto, existem diferentes implementações destes geradores, cada uma com finalidades específicas ou diferentes níveis de qualidades em relação à aleatoriedade dos números gerados.

+
+
+

Bibliotecas como a Apache Commons Math fornecem, dentre outras funcionalidades, diversos geradores de números pseudo-aleatórios.

+
+
+
+
+

1. O problema

+
+
+

Existe uma grande variedade de implementações de tais geradores, cada implementação fornecendo uma interface diferente da outra. +Para este projeto, observe o diagrama de classes abaixo.

+
+
+

random numbers

+
+
+

Ele apresenta alguns métodos da classe Random do pacote java.util e da interface RealDistribution da biblioteca Apache Commons Math. Algumas das classes que implementam esta última interface são NormalDistribution e LogNormalDistribution. Como podem ver, existem diferenças entre as classes/interfaces, tornando também diferente a forma de utilizar cada uma das implementações disponíveis.

+
+
+

A seguir são apresentados os detalhes das diferentes implementações.

+
+
+

1.1. Classe Random da plataforma Java

+
+

Na classe Random temos os métodos nextDouble() e doubles(long streamSize). Os dois podem ser utilizados para gerar números aleatórios. O primeiro gera um único número a cada vez que for chamado. O segundo gera um conjunto de números, cuja quantidade é definida pelo parâmetro streamSize. Assim, chamando doubles(3), serão gerados 3 números aleatórios.

+
+
+

Adicionalmente, esta classe possui 2 construtores: um que não recebe parâmetro algum e outro que recebe uma seed. A seed (semente) é apenas um número que define o valor inicial do gerador. Se instanciarmos um gerador com a mesma seed, a sequência de números gerados será sempre a mesma. Se alterarmos a seed ou não informarmos uma, a cada vez que executarmos a aplicação, a sequência de números gerados será diferente.

+
+
+
+

1.2. Biblioteca Apache Commons Math

+
+

Já nas classes que implementam a interface RealDistribution da biblioteca Apache Commons Math (como NormalDistribution e LogNormalDistribution), os métodos que retornam um número aleatório ou um conjunto de números são diferentes. Temos os métodos sample() e sample(int sampleSize), semelhantes aos métodos da classe Random, mas com nomes, tipos de parâmetro e retorno diferentes.

+
+
+

Por fim, nestas classes, se for preciso definir uma seed, isto não é feito por meio de um construtor, mas chamando o método reseedRandomGenerator(long seed).

+
+
+
+
+
+

2. O Desafio

+
+
+

Identifique qual padrão de projeto pode ser aplicado para uniformizar a interface das classes Random do pacote java.util e das classes que implementam a interface RealDistribution da biblioteca Apache Commons Math. O padrão deve então permitir que a forma de utilizar qualquer destas classes seja a mesma.

+
+
+

Altere a aplicação de exemplo nesta pasta (que já inclui a dependência para a biblioteca Apache Commons Math no arquivo pom.xml) para aplicar o padrão de projeto adequado. Por fim, modifique a classe Principal para utilizar as classes criadas para o padrão.

+
+
+
+
+

3. Detalhes de Implementação

+
+
+

Observe que os métodos sample(int sampleSize) da interface RealDistribution e doubles(long streamSize) da classe Random tem tipos de parâmetros e retorno diferentes. O primeiro retorna um vetor de double e o segundo retorna um objeto DoubleStream. +Uma maneira de uniformizar tais métodos é fazer com que o segundo também retorne um vetor de double. O código para isto pode ser:

+
+
+
+
double[] numeros = random.doubles(10).toArray();
+
+
+
+

Neste exemplo, estamos chamando o método doubles(), indicando que desejamos gerar 10 números aleatórios e convertendo de DoubleStream para um vetor usando o método toArray().

+
+
+

Estamos padronizando fazendo os métodos retornarem vetores, pelo fato destes serem mais familiares que Streams (como é o caso do DoubleStream). +Streams são mais modernos, seguros e flexíveis que vetores, mas vamos utilizar apenas vetores para simplificar.

+
+
+
+
+ + + + + \ No newline at end of file diff --git a/exercicios/random-numbers/index.html b/exercicios/random-numbers/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/exercicios/random-numbers/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/exercicios/real-random-number-services/README.adoc b/exercicios/real-random-number-services/README.adoc deleted file mode 100644 index 248e80b9d..000000000 --- a/exercicios/real-random-number-services/README.adoc +++ /dev/null @@ -1,107 +0,0 @@ -:sectnums: - -= Clientes para Serviços de Geração de Números Realmente Aleatórios - -== Problema - -Toda linguagem de programação possui recursos para geração de números pseudo aleatórios, como é o caso da classe Random e de bibliotecas externas para Java. - -No entanto, aplicações científicas ou mesmo sistemas de sorteio precisam de geradores realmente aleatórios. A classe SecureRandom em Java faz isso, mas ela não garante a aleatoriedade, pois isso depende de movimentos do mouse e do teclado realizados pelo usuário. - -Para gerar números realmente aleatórios, normalmente precisamos acessar um serviços que forneça tais números. Existem inúmeros serviços como o https://random.org[random.org] e https://quantumnumbers.anu.edu.au[ANU Quantum Numbers] que fornecem APIs web. Tais APIs permitem que você crie aplicações que solicitem uma determinada quantidade de números aleatórios. -Estes dois serviços possuem bibliotecas cliente que permitem acessar tais APIs facilmente a partir de programas em Java, como é o caso da https://github.com/manoelcampos/random-org-java-client[random-org-java-client] e https://github.com/manoelcampos/anu-quantum-number-java-client[anu-quantum-number-java-client]. - -No entanto, como você pode ver nos exemplos disponibilizados em cada uma das páginas apresentadas acima, cada API tem uma interface diferente e desta forma, as bibliotecas funcionam de formas distintas. -Os exemplos estão dentro da classe que implementa o cliente para a API do serviço. Assim, você pode ver quais métodos cada API disponibiliza. Mas caso prefira, no topo dos repositórios das bibliotecas há um link para o JavaDoc online das bibliotecas. - -Não existe uma padronização na forma de uso, como em nomes de métodos e parâmetros. -A maioria destes serviços cobram para serem usados em uma aplicação real. Os serviços apresentados fornecem uma conta gratuita que você terá limitações no total de números aleatórios que pode solicitar, ou até mesmo na quantidade de requisições que pode enviar para os serviços. - -Adicionalmente, um serviço pode ser mais fácil de usar do que outro, pode fornecer mais funcionalidades, ter melhor desempenho ou menos problemas de utilização. Por fim, para aplicações reais, o custo do serviço pode se tornar uma barreira. - -Com todas estas questões levantadas, depois de criar um projeto que utiliza algum desses serviços, podemos ter a necessidade de trocar o serviço por qualquer um dos motivos que acabaram de ser apresentados. - -Como não existe padronização nas APIs de tais serviços, a troca de um serviço por qualquer outro irá exigir alteração no código da sua aplicação. - -== Solução a ser Implementada - -A pasta atual possui um projeto base que já inclui as bibliotecas mencionadas como dependências no link:pom.xml[]. Implemente um _design pattern_ que garanta a padronização do uso das bibliotecas citadas, para que possamos trocar um serviço pelo outro sem termos que fazer inúmeras alterações no projeto. - - -=== Compilar e Rodar o Projeto - -O projeto requer o JDK 17 para compilar e rodar. -Para executar, é preciso fazer uma cópia do arquivo link:.env.example[] como `.env` e informar as chaves de API (API Keys) para os -serviços random.org e quantumnumbers, conforme indicado abaixo: - -- random.org - * Acesse https://accounts.random.org/create para criar uma conta. - * Efetue login em https://random.org. - * Acesse https://api.random.org/dashboard e clique na linha da tabela. Na página que abre, copie o campo "API Key". -- quantumnumbers - * Acesse https://quantumnumbers.anu.edu.au e clique em "Sign up". - * Efetue login em https://quantumnumbers.anu.edu.au. - * Acesse https://quantumnumbers.anu.edu.au/api-key e clique em "View" para copiar a chave. - -Os valores das API Keys devem ser copiados para o arquivo .env. - -=== Requisitos da Solução - -- Perceba que a classe https://github.com/manoelcampos/random-org-java-client/blob/master/src/main/java/com/manoelcampos/randomorg/RandomOrgClient.java[RandomOrgClient] já implementa uma interface bem organizada, documentada e fácil de usar. Assim, a biblioteca https://github.com/manoelcampos/anu-quantum-number-java-client[anu-quantum-number-java-client] **DEVE** utilizar tal interface para padronizar a forma de acesso ao serviço https://quantumnumbers.anu.edu.au (isto foi simplesmente uma decisão de projeto). -- Não deve ser usada nenhuma biblioteca adicional, além das que já estão incluídas no pom.xml (com exceção do Lombok, mas não é necessário). -- As classes e métodos criados precisam ter nomes o mais adequados possível. -- Duplicação de código deve ser evitada, mesmo que seja uma única linha de código. Neste projeto, e como já visto em alguns casos em aula, isto pode gerar problemas. Nem mesmo o método `main` deve ter código duplicado. Se for alcançada a padronização desejada, não haverá motivos para duplicação/redundância de código no `main`. Este é um sinal que você implementou o `design pattern` corretamente. - -=== Regras de Avaliação - -- Se o projeto não compilar ele não será avaliado. -- Princípios SOLID devem ser atendidos quando possível. -- Desorganização de código desconta pontos, de acordo com o nível do problema. -- Deve-se usar nomes adequados para variáveis, métodos, classes e interfaces. - -=== Desafios a considerar - -Algumas funcionalidades da biblioteca https://github.com/manoelcampos/random-org-java-client[random-org-java-client] não existem na https://github.com/manoelcampos/anu-quantum-number-java-client[anu-quantum-number-java-client]. Porém elas podem ser facilmente implementadas como mostrado a seguir. - -==== Gerar números distintos (sem duplicados) - -Podemos obter os números gerados pelo "ANU Quantum Numbers" (que podem conter números duplicados) e remover as duplicações implementando um método como abaixo (onde `array` é o vetor de números retornado pelo serviço): - -[source, java] ----- -/** - * Remove elementos duplicados de um vetor e retorna um novo vetor - * - * @param array vetor para remover duplicados - * @param n máximo de elementos a retornar - * @return novo vetor - */ -private int[] removeDuplicados(final int[] array, final int n) { - return Arrays.stream(array).distinct().limit(n).toArray(); -} ----- - -No entanto, se forem solicitados 10 números aleatórios ao serviço "ANU Quantum Numbers" e houver números duplicados, a função irá removê-los e não serão retornados 10 números ao usuário. **Tal problema precisa ser resolvido por você.** - -==== Gerar números dentro de uma determinada faixa - -O serviço "ANU Quantum Numbers" não deixa o usuário escolher a faixa de valores dos números aleatórios gerados. O valor mínimo é sempre zero e existem duas opções de valor máximo, dependendo da função que você chamar (255 ou 65535). -Assim, você não escolhe o valor mínimo e o valor máximo só tem 2 opções. - -No entanto, podemos permitir que o usuário escolha livremente os valores mínimo e máximo, como é feito para a API do https://random.org[random.org], com o método abaixo: - -[source, java] ----- -/** - * Altera os valores contidos em um vetor de números para que cada valor esteja - * dentro de uma faixa definida. - * @param array vetor com os números para alterar a faixa de cada valor - * @param minValue valor mínimo para cada número no vetor - * @param maxValue valor máximo para cada número no vetor - * @return o novo vetor com a mesma quantidade de elementos, - * mas cada um alterado para ficar dentro da faixa [minValue .. maxValue] - */ -private int[] alteraFaixaValores(final int[] array, final int minValue, final int maxValue) { - return Arrays.stream(array).map(val -> (val + minValue) % maxValue).toArray(); -} ----- diff --git a/exercicios/real-random-number-services/README.html b/exercicios/real-random-number-services/README.html new file mode 100644 index 000000000..06aa902dd --- /dev/null +++ b/exercicios/real-random-number-services/README.html @@ -0,0 +1,629 @@ + + + + + + + +Clientes para Serviços de Geração de Números Realmente Aleatórios + + + + + +
+
+

1. Problema

+
+
+

Toda linguagem de programação possui recursos para geração de números pseudo aleatórios, como é o caso da classe Random e de bibliotecas externas para Java.

+
+
+

No entanto, aplicações científicas ou mesmo sistemas de sorteio precisam de geradores realmente aleatórios. A classe SecureRandom em Java faz isso, mas ela não garante a aleatoriedade, pois isso depende de movimentos do mouse e do teclado realizados pelo usuário.

+
+
+

Para gerar números realmente aleatórios, normalmente precisamos acessar um serviços que forneça tais números. Existem inúmeros serviços como o random.org e ANU Quantum Numbers que fornecem APIs web. Tais APIs permitem que você crie aplicações que solicitem uma determinada quantidade de números aleatórios. +Estes dois serviços possuem bibliotecas cliente que permitem acessar tais APIs facilmente a partir de programas em Java, como é o caso da random-org-java-client e anu-quantum-number-java-client.

+
+
+

No entanto, como você pode ver nos exemplos disponibilizados em cada uma das páginas apresentadas acima, cada API tem uma interface diferente e desta forma, as bibliotecas funcionam de formas distintas. +Os exemplos estão dentro da classe que implementa o cliente para a API do serviço. Assim, você pode ver quais métodos cada API disponibiliza. Mas caso prefira, no topo dos repositórios das bibliotecas há um link para o JavaDoc online das bibliotecas.

+
+
+

Não existe uma padronização na forma de uso, como em nomes de métodos e parâmetros. +A maioria destes serviços cobram para serem usados em uma aplicação real. Os serviços apresentados fornecem uma conta gratuita que você terá limitações no total de números aleatórios que pode solicitar, ou até mesmo na quantidade de requisições que pode enviar para os serviços.

+
+
+

Adicionalmente, um serviço pode ser mais fácil de usar do que outro, pode fornecer mais funcionalidades, ter melhor desempenho ou menos problemas de utilização. Por fim, para aplicações reais, o custo do serviço pode se tornar uma barreira.

+
+
+

Com todas estas questões levantadas, depois de criar um projeto que utiliza algum desses serviços, podemos ter a necessidade de trocar o serviço por qualquer um dos motivos que acabaram de ser apresentados.

+
+
+

Como não existe padronização nas APIs de tais serviços, a troca de um serviço por qualquer outro irá exigir alteração no código da sua aplicação.

+
+
+
+
+

2. Solução a ser Implementada

+
+
+

A pasta atual possui um projeto base que já inclui as bibliotecas mencionadas como dependências no pom.xml. Implemente um design pattern que garanta a padronização do uso das bibliotecas citadas, para que possamos trocar um serviço pelo outro sem termos que fazer inúmeras alterações no projeto.

+
+
+

2.1. Compilar e Rodar o Projeto

+
+

O projeto requer o JDK 17 para compilar e rodar. +Para executar, é preciso fazer uma cópia do arquivo .env.example como .env e informar as chaves de API (API Keys) para os +serviços random.org e quantumnumbers, conforme indicado abaixo:

+
+
+ +
+
+

Os valores das API Keys devem ser copiados para o arquivo .env.

+
+
+
+

2.2. Requisitos da Solução

+
+
    +
  • +

    Perceba que a classe RandomOrgClient já implementa uma interface bem organizada, documentada e fácil de usar. Assim, a biblioteca anu-quantum-number-java-client DEVE utilizar tal interface para padronizar a forma de acesso ao serviço https://quantumnumbers.anu.edu.au (isto foi simplesmente uma decisão de projeto).

    +
  • +
  • +

    Não deve ser usada nenhuma biblioteca adicional, além das que já estão incluídas no pom.xml (com exceção do Lombok, mas não é necessário).

    +
  • +
  • +

    As classes e métodos criados precisam ter nomes o mais adequados possível.

    +
  • +
  • +

    Duplicação de código deve ser evitada, mesmo que seja uma única linha de código. Neste projeto, e como já visto em alguns casos em aula, isto pode gerar problemas. Nem mesmo o método main deve ter código duplicado. Se for alcançada a padronização desejada, não haverá motivos para duplicação/redundância de código no main. Este é um sinal que você implementou o design pattern corretamente.

    +
  • +
+
+
+
+

2.3. Regras de Avaliação

+
+
    +
  • +

    Se o projeto não compilar ele não será avaliado.

    +
  • +
  • +

    Princípios SOLID devem ser atendidos quando possível.

    +
  • +
  • +

    Desorganização de código desconta pontos, de acordo com o nível do problema.

    +
  • +
  • +

    Deve-se usar nomes adequados para variáveis, métodos, classes e interfaces.

    +
  • +
+
+
+
+

2.4. Desafios a considerar

+
+

Algumas funcionalidades da biblioteca random-org-java-client não existem na anu-quantum-number-java-client. Porém elas podem ser facilmente implementadas como mostrado a seguir.

+
+
+

2.4.1. Gerar números distintos (sem duplicados)

+
+

Podemos obter os números gerados pelo "ANU Quantum Numbers" (que podem conter números duplicados) e remover as duplicações implementando um método como abaixo (onde array é o vetor de números retornado pelo serviço):

+
+
+
+
/**
+ * Remove elementos duplicados de um vetor e retorna um novo vetor
+ *
+ * @param array vetor para remover duplicados
+ * @param n máximo de elementos a retornar
+ * @return novo vetor
+ */
+private int[] removeDuplicados(final int[] array, final int n) {
+    return Arrays.stream(array).distinct().limit(n).toArray();
+}
+
+
+
+

No entanto, se forem solicitados 10 números aleatórios ao serviço "ANU Quantum Numbers" e houver números duplicados, a função irá removê-los e não serão retornados 10 números ao usuário. Tal problema precisa ser resolvido por você.

+
+
+
+

2.4.2. Gerar números dentro de uma determinada faixa

+
+

O serviço "ANU Quantum Numbers" não deixa o usuário escolher a faixa de valores dos números aleatórios gerados. O valor mínimo é sempre zero e existem duas opções de valor máximo, dependendo da função que você chamar (255 ou 65535). +Assim, você não escolhe o valor mínimo e o valor máximo só tem 2 opções.

+
+
+

No entanto, podemos permitir que o usuário escolha livremente os valores mínimo e máximo, como é feito para a API do random.org, com o método abaixo:

+
+
+
+
/**
+ * Altera os valores contidos em um vetor de números para que cada valor esteja
+ * dentro de uma faixa definida.
+ * @param array vetor com os números para alterar a faixa de cada valor
+ * @param minValue valor mínimo para cada número no vetor
+ * @param maxValue valor máximo para cada número no vetor
+ * @return o novo vetor com a mesma quantidade de elementos,
+ *         mas cada um alterado para ficar dentro da faixa [minValue .. maxValue]
+ */
+private int[] alteraFaixaValores(final int[] array, final int minValue, final int maxValue) {
+    return Arrays.stream(array).map(val -> (val + minValue) % maxValue).toArray();
+}
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/exercicios/real-random-number-services/index.html b/exercicios/real-random-number-services/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/exercicios/real-random-number-services/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/index.html b/index.html new file mode 120000 index 000000000..b70e3e805 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ +README.html \ No newline at end of file diff --git a/links.adoc b/links.adoc deleted file mode 100644 index 109930bec..000000000 --- a/links.adoc +++ /dev/null @@ -1,22 +0,0 @@ -== Princípios Gerais - -- Keep It Simple Stupid (KISS) -- Don’t Repeat Yourself (DRY) -- https://martinfowler.com/bliki/TellDontAsk.html[Tell, Don’t Ask] -- You Ain’t Gonna Need It (YAGNI) -- Separation Of Concerns (SoC) - -== Factory - -- CDI: https://www.baeldung.com/java-ee-cdi -- https://martinfowler.com/bliki/TellDontAsk.html[Tell, Don’t Ask] -- https://en.wikipedia.org/wiki/Dependency_inversion_principle[Dependency Inversion Principle (DIP)] -- https://en.wikipedia.org/wiki/Inversion_of_control[Inversion of Control (IoC)] -- https://elmland.blog/2018/09/07/cdi-simple-factory-pattern-annotationliteral/[CDI Simple Factory] -- https://dzone.com/articles/cdi-and-the-produces-annotation-for-factory[CDI Factory with @Produces] -- http://www.thedevpiece.com/cdi-polymorphism-and-the-factory-pattern/[CDI, Polymorphism and The Factory Pattern] - - -== Geral - -- https://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns-in-javas-core-libraries \ No newline at end of file diff --git a/links.html b/links.html new file mode 100644 index 000000000..b04bcafd2 --- /dev/null +++ b/links.html @@ -0,0 +1,514 @@ + + + + + + + +Princípios Gerais + + + + + +
+
+

Princípios Gerais

+
+
+
    +
  • +

    Keep It Simple Stupid (KISS)

    +
  • +
  • +

    Don’t Repeat Yourself (DRY)

    +
  • +
  • +

    Tell, Don’t Ask

    +
  • +
  • +

    You Ain’t Gonna Need It (YAGNI)

    +
  • +
  • +

    Separation Of Concerns (SoC)

    +
  • +
+
+
+
+ + +
+ + + \ No newline at end of file diff --git a/plano-ensino-padroes-projetos.adoc b/plano-ensino-padroes-projetos.adoc deleted file mode 100644 index 9a16fe6b2..000000000 --- a/plano-ensino-padroes-projetos.adoc +++ /dev/null @@ -1,68 +0,0 @@ -# Plano de Ensino Sistemas Distribuídos - -## Ementa -Projeto e implementação de algoritmos e aplicativos orientados a objetos utilizando os padrões de projeto, que são soluções que refletem modelagens testadas e atualizadas ao longo do tempo. - -## Justificativa - -### Competências -Compreender os padrões de criação e estruturais; Compreender e implementar padrões comportamentais; Prestar assistência técnica e consultoria. - -### Habilidades -Realização de projetos de algoritmos orientados a objetos, utilizando padrões de projeto; -Desenvolvimento e aplicação de padrões de projeto; -Relacionamento dos padrões de projeto com os padrões/estilos arquiteturais e linguagens de programação. - -## Objetivo Geral - -Compreender os principais padrões de projetos e suas aplicações para resolução de problemas rotineiros de modelagem de software. - -## Objetivos Específicos - -- Compreender o que são padrões de projetos -- Compreender finalidades e categorias de padrões -- Identificar padrões de projetos -- Entender características de padrões -- Conhecer a finalidade de determinado padrão -- Entender como aplicar um padrão de projeto para resolver um problema de software -- Entender os princípios de engenharia de software envolvidos em cada padrão de projeto -- Implementar soluções com padrões de projetos - -## Conteúdo Programático - -- #0 🎤 Apresentação e Material da Disciplina -- #1 Introdução Padrões de Projetos -- #2 ♟Comportamental: Padrão Strategy -- #3 🧾 Strategy: Exemplo Realista -- #4 👩🏽‍💻 Programação Funcional -- #5 ♟👩🏽‍💻 Strategy c/ Prog. Funcional -- #6 📄 Comportamental: Template Method -- #7 🏭 Criacionais: Factories (Fábricas) -- #8 👨‍🏭 Criacionais: Factory Method -- #9 💉 Criacionais: Fábricas com CDI -- #10 🙋🏽‍♂️ Criacionais: Singleton -- #11 🙋🏽‍♂️💉 Criacionais: Singleton e CDI -- #12 👷🏽‍♂️🛠 Criacionais: Builder -- #13 🏗🏛 Estruturais -- #14 👩🏽‍💻 Exercícios: Descubra e aplique padrões -- #15 👩🏽‍💻 Exercícios: Descubra e aplique padrões - - -## Metodologia - -Aulas expositivas e práticas em laboratório, com desenvolvimento de projetos. - - -## Bibliografia Básica - -✅ FREEMAN, Eric: Use a cabeça Padrões de Projeto - Rio de Janeiro: Alta Books, 2009. -✅ GAMMA, Erich; Padrões de projeto soluções reutilizáveis de software orientado - Porto Alegre: Bookman, 2000. -✅ METSKER, Steven John: Padrões de projeto em java - Porto Alegre: Bookman, 2004. - - -## Bibliografia Complementar - -✅ OLIVEIRA, Jayr Figueiredo de; Metodologia para Desenvolvimento de Projetos de Sistemas; São Paulo: Érica, 1999. -✅ PAULA FILHO, Wilson de Pádua; Engenharia de software: fundamentos, métodos e padrões. Rio de Janeiro: LTC, 2005. padrões.Rio de Janeiro: LTC, 2005. -✅ SILVA, Nelson Peres da; Projeto e Desenvolvimento de Sistemas; São Paulo: Érica, 1998. - diff --git a/plano-ensino-padroes-projetos.html b/plano-ensino-padroes-projetos.html new file mode 100644 index 000000000..885119f96 --- /dev/null +++ b/plano-ensino-padroes-projetos.html @@ -0,0 +1,602 @@ + + + + + + + +Plano de Ensino Sistemas Distribuídos + + + + + +
+
+

Ementa

+
+
+

Projeto e implementação de algoritmos e aplicativos orientados a objetos utilizando os padrões de projeto, que são soluções que refletem modelagens testadas e atualizadas ao longo do tempo.

+
+
+
+
+

Justificativa

+
+
+

Competências

+
+

Compreender os padrões de criação e estruturais; Compreender e implementar padrões comportamentais; Prestar assistência técnica e consultoria.

+
+
+
+

Habilidades

+
+

Realização de projetos de algoritmos orientados a objetos, utilizando padrões de projeto; +Desenvolvimento e aplicação de padrões de projeto; +Relacionamento dos padrões de projeto com os padrões/estilos arquiteturais e linguagens de programação.

+
+
+
+
+
+

Objetivo Geral

+
+
+

Compreender os principais padrões de projetos e suas aplicações para resolução de problemas rotineiros de modelagem de software.

+
+
+
+
+

Objetivos Específicos

+
+
+
    +
  • +

    Compreender o que são padrões de projetos

    +
  • +
  • +

    Compreender finalidades e categorias de padrões

    +
  • +
  • +

    Identificar padrões de projetos

    +
  • +
  • +

    Entender características de padrões

    +
  • +
  • +

    Conhecer a finalidade de determinado padrão

    +
  • +
  • +

    Entender como aplicar um padrão de projeto para resolver um problema de software

    +
  • +
  • +

    Entender os princípios de engenharia de software envolvidos em cada padrão de projeto

    +
  • +
  • +

    Implementar soluções com padrões de projetos

    +
  • +
+
+
+
+
+

Conteúdo Programático

+
+
+
    +
  • +

    #0 🎤 Apresentação e Material da Disciplina

    +
  • +
  • +

    #1 Introdução Padrões de Projetos

    +
  • +
  • +

    #2 ♟Comportamental: Padrão Strategy

    +
  • +
  • +

    #3 🧾 Strategy: Exemplo Realista

    +
  • +
  • +

    #4 👩🏽‍💻 Programação Funcional

    +
  • +
  • +

    #5 ♟👩🏽‍💻 Strategy c/ Prog. Funcional

    +
  • +
  • +

    #6 📄 Comportamental: Template Method

    +
  • +
  • +

    #7 🏭 Criacionais: Factories (Fábricas)

    +
  • +
  • +

    #8 👨‍🏭 Criacionais: Factory Method

    +
  • +
  • +

    #9 💉 Criacionais: Fábricas com CDI

    +
  • +
  • +

    #10 🙋🏽‍♂️ Criacionais: Singleton

    +
  • +
  • +

    #11 🙋🏽‍♂️💉 Criacionais: Singleton e CDI

    +
  • +
  • +

    #12 👷🏽‍♂️🛠 Criacionais: Builder

    +
  • +
  • +

    #13 🏗🏛 Estruturais

    +
  • +
  • +

    #14 👩🏽‍💻 Exercícios: Descubra e aplique padrões

    +
  • +
  • +

    #15 👩🏽‍💻 Exercícios: Descubra e aplique padrões

    +
  • +
+
+
+
+
+

Metodologia

+
+
+

Aulas expositivas e práticas em laboratório, com desenvolvimento de projetos.

+
+
+
+
+

Bibliografia Básica

+
+
+

✅ FREEMAN, Eric: Use a cabeça Padrões de Projeto - Rio de Janeiro: Alta Books, 2009. +✅ GAMMA, Erich; Padrões de projeto soluções reutilizáveis de software orientado - Porto Alegre: Bookman, 2000. +✅ METSKER, Steven John: Padrões de projeto em java - Porto Alegre: Bookman, 2004.

+
+
+
+
+

Bibliografia Complementar

+
+
+

✅ OLIVEIRA, Jayr Figueiredo de; Metodologia para Desenvolvimento de Projetos de Sistemas; São Paulo: Érica, 1999. +✅ PAULA FILHO, Wilson de Pádua; Engenharia de software: fundamentos, métodos e padrões. Rio de Janeiro: LTC, 2005. padrões.Rio de Janeiro: LTC, 2005. +✅ SILVA, Nelson Peres da; Projeto e Desenvolvimento de Sistemas; São Paulo: Érica, 1998.

+
+
+
+
+ + + \ No newline at end of file