{"id":2163,"date":"2019-08-30T22:31:23","date_gmt":"2019-08-30T19:31:23","guid":{"rendered":"http:\/\/demensdeum.com\/blog\/?p=2163"},"modified":"2024-12-16T22:32:35","modified_gmt":"2024-12-16T19:32:35","slug":"pattern-delegate","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/pt\/2019\/08\/30\/pattern-delegate\/","title":{"rendered":"Padr\u00e3o de delegado"},"content":{"rendered":"<p>O padr\u00e3o delegado \u00e9 um dos principais padr\u00f5es de design.<br \/>Digamos que estamos desenvolvendo um aplicativo para uma barbearia. O aplicativo possui um calend\u00e1rio para sele\u00e7\u00e3o de um dia para grava\u00e7\u00e3o; ao tocar na data dever\u00e1 abrir uma lista de barbeiros com op\u00e7\u00e3o.<br \/>Vamos implementar uma liga\u00e7\u00e3o ing\u00eanua de componentes do sistema, combinar o calend\u00e1rio e a tela usando ponteiros entre si para implementar uma exibi\u00e7\u00e3o de lista:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\n\/\/ \u043f\u0441\u0435\u0432\u0434\u043e\u043a\u043e\u0434\n\nclass BarbershopScreen {\n   let calendar: Calendar\n\n   func showBarbersList(date: Date) {\n      showSelectionSheet(barbers(forDate: date))\n   }\n}\n\nclass Calendar {\n    let screen: BarbershopScreen\n\n    func handleTap(on date: Date) {\n        screen.showBarbersList(date: date)\n    }\n}\n<\/code><\/pre>\n<\/div>\n<p>Depois de alguns dias, os requisitos mudam; antes de exibir a lista, \u00e9 necess\u00e1rio mostrar ofertas com op\u00e7\u00e3o de servi\u00e7os (aparar barba, etc.), mas nem sempre, em todos os dias, exceto s\u00e1bado.<br \/>Adicionamos ao calend\u00e1rio uma verifica\u00e7\u00e3o se \u00e9 s\u00e1bado ou n\u00e3o, dependendo disso chamamos o m\u00e9todo da lista de barbeiros ou da lista de servi\u00e7os, para maior clareza irei demonstrar:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\n\/\/ \u043f\u0441\u0435\u0432\u0434\u043e\u043a\u043e\u0434\n\nclass BarbershopScreen {\n   let calendar: Calendar\n\n   func showBarbersList(date: Date) {\n      showSelectionSheet(barbers(forDate: date))\n   }\n\n   func showOffersList() {\n      showSelectionSheet(offers)\n   }\n}\n\nclass Calendar {\n    let screen: BarbershopScreen\n\n    func handleTap(on date: Date)  {\n        if date.day != .saturday {\n             screen.showOffersList()\n        }\n        else {\n             screen.showBarbersList(date: date)\n        }\n    }\n}\n<\/code><\/pre>\n<\/div>\n<p>Uma semana depois, somos solicitados a adicionar um calend\u00e1rio \u00e0 tela de feedback e, nesse momento, acontece o primeiro erro arquitet\u00f4nico!<br \/>O que fazer? O calend\u00e1rio est\u00e1 intimamente ligado \u00e0 tela de marca\u00e7\u00e3o de corte de cabelo.<br \/>uau! eca! ah ah<br \/>Se voc\u00ea continuar trabalhando com essa arquitetura maluca de aplica\u00e7\u00e3o, voc\u00ea deve fazer uma c\u00f3pia de toda a classe de calend\u00e1rio e associar essa c\u00f3pia \u00e0 tela de feedback.<br \/>Ok, parece bom, ent\u00e3o adicionamos mais algumas telas e v\u00e1rias c\u00f3pias do calend\u00e1rio, e ent\u00e3o chegou o momento X. Fomos solicitados a alterar o design do calend\u00e1rio, o que significa que agora precisamos encontrar todas as c\u00f3pias do calend\u00e1rio e adicionar as mesmas altera\u00e7\u00f5es a todas. Essa \u201cabordagem\u201d afeta muito a velocidade de desenvolvimento e aumenta a chance de cometer erros. Como resultado, tais projetos acabam em um estado quebrado, quando at\u00e9 mesmo o autor da arquitetura original n\u00e3o entende mais como funcionam as c\u00f3pias de suas aulas, e outros hacks adicionados ao longo do caminho desmoronam na hora.<br \/>O que precisava ser feito, ou melhor ainda, o que n\u00e3o era tarde demais para come\u00e7ar a fazer? Use o padr\u00e3o de delega\u00e7\u00e3o!<br \/>A delega\u00e7\u00e3o \u00e9 uma forma de passar eventos de classe por meio de uma interface comum. Abaixo est\u00e1 um exemplo de delegado para um calend\u00e1rio:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>protocol CalendarDelegate {\n   func calendar(_ calendar: Calendar, didSelect date: Date)\n}\n<\/code><\/pre>\n<\/div>\n<p>Agora vamos adicionar o c\u00f3digo para trabalhar com o delegado ao c\u00f3digo de exemplo:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\n\/\/ \u043f\u0441\u0435\u0432\u0434\u043e\u043a\u043e\u0434\n\nclass BarbershopScreen: CalendarDelegate {\n   let calendar: Calendar\n\n   init() {\n       calendar.delegate = self\n   }\n\n   func calendar(_ calendar: Calendar, didSelect date: Date) {\n        if date.day != .saturday {\n            showOffersList()\n        }\n        else {\n             showBarbersList(date: date)\n        }\n   }\n\n   func showBarbersList(date: Date) {\n      showSelectionSheet(barbers(forDate: date))\n   }\n\n   func showOffersList() {\n      showSelectionSheet(offers)\n   }\n}\n\nclass Calendar {\n    weak var delegate: CalendarDelegate\n\n    func handleTap(on date: Date)  {\n        delegate?.calendar(self, didSelect: date)\n    }\n}\n<\/code><\/pre>\n<\/div>\n<p>Como resultado, desvinculamos completamente o calend\u00e1rio da tela ao selecionar uma data no calend\u00e1rio, ele transmite o evento de sele\u00e7\u00e3o de data &#8211; *delega* processamento de eventos ao assinante; O assinante \u00e9 a tela.<br \/>Que benef\u00edcios obtemos com esta abordagem? Agora podemos alterar a l\u00f3gica do calend\u00e1rio e da tela de forma independente, sem duplicar classes, simplificando ainda mais o suporte; Desta forma, \u00e9 implementado o \u201cprinc\u00edpio da responsabilidade exclusiva\u201d pela implementa\u00e7\u00e3o dos componentes do sistema e observado o princ\u00edpio DRY.<br \/>Ao usar a delega\u00e7\u00e3o, voc\u00ea pode adicionar, alterar a l\u00f3gica de exibi\u00e7\u00e3o das janelas, a ordem de qualquer coisa na tela, e isso n\u00e3o afetar\u00e1 em nada o calend\u00e1rio e outras classes, que objetivamente n\u00e3o devem participar de processos n\u00e3o diretamente relacionados a elas.< br\/>Alternativamente, os programadores que n\u00e3o se preocupam muito usam o envio de mensagens atrav\u00e9s de um barramento comum, sem escrever uma interface separada de protocolo\/delegado, onde seria melhor usar a delega\u00e7\u00e3o. Escrevi sobre as desvantagens dessa abordagem em um post anterior &#038; # 8211; \u201cPadr\u00e3o do Observador.\u201d<\/p>\n<h3>Fontes<\/h3>\n<p><a href=\"https:\/\/refactoring.guru\/ru\/replace-inheritance-with-delegation\" target=\"_blank\" rel=\"noopener\">https:\/\/refactoring.guru\/ru\/replace-inheritance -com delega\u00e7\u00e3o<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>O padr\u00e3o delegado \u00e9 um dos principais padr\u00f5es de design.Digamos que estamos desenvolvendo um aplicativo para uma barbearia. O aplicativo possui um calend\u00e1rio para sele\u00e7\u00e3o de um dia para grava\u00e7\u00e3o; ao tocar na data dever\u00e1 abrir uma lista de barbeiros com op\u00e7\u00e3o.Vamos implementar uma liga\u00e7\u00e3o ing\u00eanua de componentes do sistema, combinar o calend\u00e1rio e a<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/pt\/2019\/08\/30\/pattern-delegate\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Padr\u00e3o de delegado&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[61,52],"tags":[114,95],"class_list":["post-2163","post","type-post","status-publish","format-standard","hentry","category-techie","category-tutorials","tag-delegate","tag-patterns","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"pt","enabled_languages":["en","ru","zh","de","fr","ja","pt","hi"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false},"hi":{"title":false,"content":false,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2163","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=2163"}],"version-history":[{"count":6,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2163\/revisions"}],"predecessor-version":[{"id":3946,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/2163\/revisions\/3946"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=2163"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=2163"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=2163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}