{"componentChunkName":"component---src-templates-blog-post-js","path":"/python-design-patterns/","result":{"data":{"markdownRemark":{"html":"<h2 id=\"Definicao-do-projeto\" style=\"position:relative;\">Definição do projeto<a href=\"#Definicao-do-projeto\" aria-label=\"Definicao do projeto permalink\" class=\"anchor after\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\n<p>Continuando essa série de posts sobre design patterns, já foi mostrado como usar em <a href=\"https://programadev.com.br/factory-strategy/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Java</a> e <a href=\"https://programadev.com.br/go-design-patterns/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Go</a> e agora vamos mostrar como usar com Python também, vamos ver como padrões de projeto nos ajudam a ter um código limpo, reutilizável e de fácil manutenção e alterações caso necessário.\nEntão vamos pensar no cenário, temos uma aplicação que vai salvar Notas Fiscais (Invoices), nesse caso vamos ter entrada de vários tipos diferentes de notas e precisamos processar diferentemente cada nota, precisamos descobrir então qual o tipo de nota está chegando e executar a lógica de cálculo de taxas, após isso precisamos salvar essa informação mas de antemão nós não sabemos onde isso será salvo, se vai ser em banco de dados ou em um bucket ou até mesmo um arquivo <em>txt</em> simples salvo na máquina e por fim recebemos a demanda de que para cada nota salva o departamento fiscal e o financeiro querem ser notificados disso.</p>\n<h2 id=\"Factory\" style=\"position:relative;\">Factory<a href=\"#Factory\" aria-label=\"Factory permalink\" class=\"anchor after\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\n<p>Esse padrão está no grupo dos padrões criacionais e nos ajuda quando precisamos criar objetos baseados em uma superclasse, no nosso exemplo temos um domínio que seria a Nota Fiscal mas não sabemos que tipo de nota seria essa, será um ICMS, ISS ou outra que ainda nem definimos e que pode vir a aparecer por alguma exigência legal ou fiscal. <em>(Não sei nada sobre notas fiscais pra dizer se ICMS é uma nota sozinha mas o exemplo aqui é para entender que existem notas diferentes mas no fim são todas Notas Fiscais)</em>.\nEntão com essa ideia vamos criar o super tipo ou interface ou classe abstrata, isso vária um pouco de linguagem pra linguagem mas a ideia aqui é ter um “molde” para as nossas notas, vamos criar a classe <strong>Invoice</strong>:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> abc <span class=\"token keyword\">import</span> ABC<span class=\"token punctuation\">,</span> abstractmethod\n\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Invoice</span><span class=\"token punctuation\">(</span>ABC<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n\n    <span class=\"token decorator annotation punctuation\">@abstractmethod</span>\n    <span class=\"token keyword\">def</span> <span class=\"token function\">calculate_rate</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">pass</span></code></pre></div>\n<p>Aqui temos a nossa classe <strong>Invoice</strong> e ela é uma classe abstrata com um método não implementado chamado <em>calculate_rate</em> então aqui temos uma classe que nos obriga a implementar esse método para quem herdar dela.\nVamos então criar as suas filhas que serão as classes <strong>InvoiceIcms</strong> e <strong>InvoiceIss</strong>:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>invoice <span class=\"token keyword\">import</span> Invoice\n\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">InvoiceIss</span><span class=\"token punctuation\">(</span>Invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">def</span> <span class=\"token function\">calculate_rate</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string\">\"Processing Iss tax\"</span></code></pre></div>\n<p>As duas seguem o mesmo modelo para o nosso exemplo, pra simplificar temos a classe que herda uma <strong>Invoice</strong> então essa classe é uma <strong>Invoice</strong> e a implementação do método <em>calculate_rate</em>.\nEntão até aqui temos só o que seria a estrutura ainda nada referente a como iremos criar esses objetos, vamos então criar a nossa fábrica especializada em criar tipos <strong>Invoice</strong> e que saiba é uma <strong>InvoiceIcms</strong> ou uma <strong>InvoiceIss</strong>:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>invoice <span class=\"token keyword\">import</span> Invoice\n<span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>invoice_iss <span class=\"token keyword\">import</span> InvoiceIss\n<span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>invoice_icms <span class=\"token keyword\">import</span> InvoiceIcms\n\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">InvoiceFactory</span><span class=\"token punctuation\">:</span>\n\n    <span class=\"token decorator annotation punctuation\">@staticmethod</span>\n    <span class=\"token keyword\">def</span> <span class=\"token function\">create_invoice</span><span class=\"token punctuation\">(</span>name<span class=\"token punctuation\">:</span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> Invoice<span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">if</span> name <span class=\"token operator\">==</span> <span class=\"token string\">\"ICMS\"</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span> InvoiceIcms<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">return</span> InvoiceIss<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>A primeira vista uma factory desse tipo não parece ser algo tão vantajoso  e que não tem nada de mais com o que vemos no nosso dia-a-dia mas para esses casos eu gosto de citar o que disse o Uncle Bob a respeito disso no livro <em>Clean Code</em>:\n<em>“A solução é inserir a estrutura switch no fundo de uma ABSTRACT FACTORY e jamais deixar que alguém a veja. A factory usará o switch para criar instâncias apropriadas derivadas… Minha regra geral para estruturas switch é que são aceitáveis se aparecerem apenas uma vez, como criação de objetos polimórficos, e se estiverem escondidas, atrás de uma relação de herança de mode que o resto do sistema não possa enxergá-la.”</em></p>\n<p>Como não temos <code class=\"language-text\">switch</code> em Python vamos usar a estrutura <code class=\"language-text\">if/else</code>.\nPor fim temos como criar os nossos objetos de uma forma mais centralizada e quem chama a <em>factory</em> não se preocupa com a forma que os objetos são criados mas se preocupam somente na ideia de usar os objetos criados:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">invoice_icms <span class=\"token operator\">=</span> <span class=\"token string\">\"ICMS\"</span>\ninvoice_iss <span class=\"token operator\">=</span> <span class=\"token string\">\"ISS\"</span>\n\n\ninvoice <span class=\"token operator\">=</span> InvoiceFactory<span class=\"token punctuation\">.</span>create_invoice<span class=\"token punctuation\">(</span>invoice_icms<span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">.</span>calculate_rate<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\ninvoice <span class=\"token operator\">=</span> InvoiceFactory<span class=\"token punctuation\">.</span>create_invoice<span class=\"token punctuation\">(</span>invoice_iss<span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">.</span>calculate_rate<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Agora temos a nossa <strong>Invoice</strong> certa sendo construída e o cálculo correto pra cada tipo.</p>\n<h2 id=\"Adapter\" style=\"position:relative;\">Adapter<a href=\"#Adapter\" aria-label=\"Adapter permalink\" class=\"anchor after\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\n<p>Agora vamos pensar na seguinte situação, temos o nosso cálculo sendo feito e o processamento acontecendo mas precisamos guardar esse dado em algum lugar, mas onde? Em um banco de dados, mas em qual? Enviar esse dado em um sistema de mensageria, mas qual? Kafka? RabbitMQ? Será que isso é algo devemos nos preocupar agora? </p>\n<p>Pensando na ideia de implementação tardia, onde os detalhes serão pensados no futuro e que a nossa solução tem que ser pensada no negócio e não nas tecnologias envolvidas o padrão <strong>Adapter</strong> nos ajuda e muito com isso.</p>\n<p>A ideia aqui é que eu exponha um contrato do que eu preciso que seja feito e posteriormente será implementada a solução, vamos começar a criar para exemplificar melhor:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> abc <span class=\"token keyword\">import</span> ABC\n<span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>invoice <span class=\"token keyword\">import</span> Invoice\n\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Repository</span><span class=\"token punctuation\">(</span>ABC<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">def</span> <span class=\"token function\">save</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">:</span> Invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">pass</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">get_one</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> identity<span class=\"token punctuation\">:</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">pass</span></code></pre></div>\n<p>Aqui nós temos a nossa <strong>Repository</strong> que funciona como o nosso contrato declarando a assinatura dos nossos métodos sem implementação.\nVamos então para a nossa implementação e aqui vamos supor que para o nosso desenvolvimento e testes somente salvando os dados em um <em>.txt</em> é o suficiente para nós, então criamos assim:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> adapter<span class=\"token punctuation\">.</span>repository <span class=\"token keyword\">import</span> Repository\n<span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>invoice <span class=\"token keyword\">import</span> Invoice\n\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">FileSystemStorage</span><span class=\"token punctuation\">(</span>Repository<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">save</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">:</span> Invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"Saving with class </span><span class=\"token interpolation\"><span class=\"token punctuation\">{</span><span class=\"token builtin\">type</span><span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>__name__<span class=\"token punctuation\">}</span></span><span class=\"token string\">\"</span></span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">get_one</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> identity<span class=\"token punctuation\">:</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string-interpolation\"><span class=\"token string\">f'FileSystemStorage#get_one'</span></span></code></pre></div>\n<p>Aqui é só um exemplo básico onde no método <em>save</em> eu exibo o nome da classe que foi passado e no get_one é devolvido uma string fixa, mas mesmo essa implementação é aderente ao contrato do nosso <strong>Adapter</strong>.\nAinda vamos criar mais uma camada aqui só para emular o caso em que precisamos fazer alguma preparação pro nosso <strong>Repository</strong>:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> adapter<span class=\"token punctuation\">.</span>repository <span class=\"token keyword\">import</span> Repository\n<span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>invoice <span class=\"token keyword\">import</span> Invoice\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">save</span><span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">:</span> Repository<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">:</span> Invoice<span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token boolean\">None</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Preparing to save\"</span><span class=\"token punctuation\">)</span>\n    repository<span class=\"token punctuation\">.</span>save<span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">)</span>\n\n\n<span class=\"token keyword\">def</span> <span class=\"token function\">get_one</span><span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">:</span> Repository<span class=\"token punctuation\">,</span> identity<span class=\"token punctuation\">:</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Preparing to get from storage\"</span><span class=\"token punctuation\">)</span>\n    repository<span class=\"token punctuation\">.</span>get_one<span class=\"token punctuation\">(</span>identity<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Pronto, com isso já podemos usar o nosso <strong>Adapter</strong> e a vantagem que temos é que conseguimos seguir o nosso desenvolvimento sem ficar acoplado ou preso a nenhuma tecnologia, se depois da nossa entrega for definido que vão usar o banco de dados X ou Y o trabalho que temos é criar outra classe que use esse banco de dados mas que implemente a nossa <strong>Repository</strong> e com isso fica transparente pra quem usa esses detalhes de implementação, aqui abaixo segue um exemplo caso usasse um banco de dados:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> adapter<span class=\"token punctuation\">.</span>repository <span class=\"token keyword\">import</span> Repository\n<span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>invoice <span class=\"token keyword\">import</span> Invoice\n\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Database</span><span class=\"token punctuation\">(</span>Repository<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">save</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">:</span> Invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"Loading specifics configs for the Database X\"</span></span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"Saving with class </span><span class=\"token interpolation\"><span class=\"token punctuation\">{</span><span class=\"token builtin\">type</span><span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>__name__<span class=\"token punctuation\">}</span></span><span class=\"token string\">\"</span></span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">get_one</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> identity<span class=\"token punctuation\">:</span> <span class=\"token builtin\">int</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span><span class=\"token operator\">></span> <span class=\"token builtin\">str</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f\"Loading specifics configs for the Database X\"</span></span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string-interpolation\"><span class=\"token string\">f'Database#get_one'</span></span></code></pre></div>\n<p>E a utilização do nosso <strong>Adapter</strong>:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">repository <span class=\"token operator\">=</span> Database<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\nsave<span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">)</span>\n\nget_one<span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n\nrepository <span class=\"token operator\">=</span> FileSystemStorage<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\nsave<span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">)</span>\n\nget_one<span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h2 id=\"Observer\" style=\"position:relative;\">Observer<a href=\"#Observer\" aria-label=\"Observer permalink\" class=\"anchor after\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\n<p>Agora já podemos criar as nossas <strong>Invoices</strong> dependendo da sua entrada e conseguimos salvar sem nos preocupar com os detalhes de implementação mas ainda falta o último requisito que é enviar para os departamentos interessados a notificação de que salvamos as <strong>Invoices</strong>.\nPodemos ao fim de cada método <em>save</em> fazer algo como:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">sendEmail<span class=\"token punctuation\">(</span><span class=\"token string\">\"dpt_financial\"</span><span class=\"token punctuation\">)</span>\nsendEmail<span class=\"token punctuation\">(</span><span class=\"token string\">\"dpt_fiscal\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>E isso vai funcionar mas vamos pensar que entrou mais um departamento interessado na criação de <strong>Invoices</strong> ou então mudou a regra e agora cada pessoa desses departamentos irão receber e são 50 pessoas em cada departamento.</p>\n<p>Vamos ficar entrando sempre no código e aumentar o método ou fazer um <code class=\"language-text\">for</code> em uma lista de emails ou departamentos?\nE se tivesse como eu me inscrever como interessado nesse assunto e toda vez que eu um <em>save</em> ocorrer eu seja notificado? Acredito que seria mais simples até mesmo caso onde eu não queira mais receber notificações eu só iria me desinscrever nesse assunto sem nenhum problema.</p>\n<p>Esse seria o padrão <strong>Observer</strong> onde eu crio um objeto que fica literalmente observando e recebe notificações nos assuntos que eu me inscrevi.</p>\n<p>Então vamos começar criando a nossa classe <strong>Observer</strong> que vai ser responsável por criar propriamente dito os observadores e que tem o método que diz o que deve acontecer quando uma notificação for enviada:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">EmailObserver</span><span class=\"token punctuation\">:</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> email<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        self<span class=\"token punctuation\">.</span>__email <span class=\"token operator\">=</span> email\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">update</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span><span class=\"token string-interpolation\"><span class=\"token string\">f'For </span><span class=\"token interpolation\"><span class=\"token punctuation\">{</span>self<span class=\"token punctuation\">.</span>__email<span class=\"token punctuation\">}</span></span><span class=\"token string\">, send report about </span><span class=\"token interpolation\"><span class=\"token punctuation\">{</span>invoice<span class=\"token punctuation\">}</span></span><span class=\"token string\">'</span></span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Aqui só temos o nosso inicializador que recebe o email e o método <em>update</em> que recebe o a <strong>Invoice</strong> para montar a mensagem.\nE agora vamos criar o nosso <strong>Subject</strong> que representa o nosso assunto a ser inscrito e que contém os métodos para se inscrever, desinscrever e notificar:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">EmailSubject</span><span class=\"token punctuation\">:</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">__init__</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        self<span class=\"token punctuation\">.</span>__subscribers <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">add_email</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> subject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        self<span class=\"token punctuation\">.</span>notify_subscribers<span class=\"token punctuation\">(</span>subject<span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">subscribe</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> subscriber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        self<span class=\"token punctuation\">.</span>__subscribers<span class=\"token punctuation\">.</span>append<span class=\"token punctuation\">(</span>subscriber<span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">unsubscribe</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> subscriber<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> self<span class=\"token punctuation\">.</span>__subscribers<span class=\"token punctuation\">.</span>remove<span class=\"token punctuation\">(</span>subscriber<span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">subscribers</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> self<span class=\"token punctuation\">.</span>__subscribers\n\n    <span class=\"token keyword\">def</span> <span class=\"token function\">notify_subscribers</span><span class=\"token punctuation\">(</span>self<span class=\"token punctuation\">,</span> subject<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">for</span> sub <span class=\"token keyword\">in</span> self<span class=\"token punctuation\">.</span>__subscribers<span class=\"token punctuation\">:</span>\n            sub<span class=\"token punctuation\">.</span>update<span class=\"token punctuation\">(</span>subject<span class=\"token punctuation\">)</span></code></pre></div>\n<p>O estado interno dessa classe contém um array de <em>subscribers</em> onde eu adiciono um novo ou removo com os métodos <em>subscribe</em> e <em>unsubscribe</em> e o método para notificar todos os inscritos com <em>notify_subscribers</em>.\nE para fazer uso dele podemos fazer o seguinte:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\">fiscal <span class=\"token operator\">=</span> EmailObserver<span class=\"token punctuation\">(</span><span class=\"token string\">\"dept_fiscal\"</span><span class=\"token punctuation\">)</span>\nfinancial <span class=\"token operator\">=</span> EmailObserver<span class=\"token punctuation\">(</span><span class=\"token string\">\"dept_financial\"</span><span class=\"token punctuation\">)</span>\nsubject<span class=\"token punctuation\">.</span>subscribe<span class=\"token punctuation\">(</span>fiscal<span class=\"token punctuation\">)</span>\nsubject<span class=\"token punctuation\">.</span>subscribe<span class=\"token punctuation\">(</span>financial<span class=\"token punctuation\">)</span>\nsubject<span class=\"token punctuation\">.</span>add_email<span class=\"token punctuation\">(</span><span class=\"token string\">\"ICMS\"</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>E com isso temos o ganho de inscrever somente uma vez e toda vez que o <em>add_email</em> for invocado irá notificar a todos.</p>\n<h2 id=\"Projeto-completo\" style=\"position:relative;\">Projeto completo<a href=\"#Projeto-completo\" aria-label=\"Projeto completo permalink\" class=\"anchor after\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a></h2>\n<p>Segue abaixo o projeto completo e o projeto no <a href=\"https://github.com/guilhermegarcia86/python-design-patterns\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Github</a>:</p>\n<div class=\"gatsby-highlight\" data-language=\"python\"><pre class=\"language-python\"><code class=\"language-python\"><span class=\"token keyword\">from</span> adapter<span class=\"token punctuation\">.</span>database <span class=\"token keyword\">import</span> Database\n<span class=\"token keyword\">from</span> adapter<span class=\"token punctuation\">.</span>file_system_storage <span class=\"token keyword\">import</span> FileSystemStorage\n<span class=\"token keyword\">from</span> adapter<span class=\"token punctuation\">.</span>adapter <span class=\"token keyword\">import</span> save<span class=\"token punctuation\">,</span> get_one\n<span class=\"token keyword\">from</span> factory<span class=\"token punctuation\">.</span>factory <span class=\"token keyword\">import</span> InvoiceFactory\n<span class=\"token keyword\">from</span> observer<span class=\"token punctuation\">.</span>email_observer <span class=\"token keyword\">import</span> EmailObserver\n<span class=\"token keyword\">from</span> observer<span class=\"token punctuation\">.</span>email_subject <span class=\"token keyword\">import</span> EmailSubject\n\ninvoice_icms <span class=\"token operator\">=</span> <span class=\"token string\">\"ICMS\"</span>\ninvoice_iss <span class=\"token operator\">=</span> <span class=\"token string\">\"ISS\"</span>\n\nsubject <span class=\"token operator\">=</span> EmailSubject<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\nfiscal <span class=\"token operator\">=</span> EmailObserver<span class=\"token punctuation\">(</span><span class=\"token string\">\"dept_fiscal\"</span><span class=\"token punctuation\">)</span>\nfinancial <span class=\"token operator\">=</span> EmailObserver<span class=\"token punctuation\">(</span><span class=\"token string\">\"dept_financial\"</span><span class=\"token punctuation\">)</span>\nsubject<span class=\"token punctuation\">.</span>subscribe<span class=\"token punctuation\">(</span>fiscal<span class=\"token punctuation\">)</span>\nsubject<span class=\"token punctuation\">.</span>subscribe<span class=\"token punctuation\">(</span>financial<span class=\"token punctuation\">)</span>\n\ninvoice <span class=\"token operator\">=</span> InvoiceFactory<span class=\"token punctuation\">.</span>create_invoice<span class=\"token punctuation\">(</span>invoice_icms<span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">.</span>calculate_rate<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\nrepository <span class=\"token operator\">=</span> Database<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\nsave<span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">)</span>\n\nsubject<span class=\"token punctuation\">.</span>add_email<span class=\"token punctuation\">(</span><span class=\"token builtin\">type</span><span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>__name__<span class=\"token punctuation\">)</span>\n\nget_one<span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n\ninvoice <span class=\"token operator\">=</span> InvoiceFactory<span class=\"token punctuation\">.</span>create_invoice<span class=\"token punctuation\">(</span>invoice_iss<span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">print</span><span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">.</span>calculate_rate<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n\nrepository <span class=\"token operator\">=</span> FileSystemStorage<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\nsave<span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">,</span> invoice<span class=\"token punctuation\">)</span>\n\nsubject<span class=\"token punctuation\">.</span>add_email<span class=\"token punctuation\">(</span><span class=\"token builtin\">type</span><span class=\"token punctuation\">(</span>invoice<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>__name__<span class=\"token punctuation\">)</span>\n\nget_one<span class=\"token punctuation\">(</span>repository<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span></code></pre></div>","fields":{"slug":"/python-design-patterns/"},"frontmatter":{"date":"28 de setembro de 2020","description":"Utilizando padrões Adapter, Factory e Observer","title":"Padrões de projeto com Python","tags":["Desenvolvimento","Python","Design Patterns"],"author":"Guilherme Alves","image":{"id":"4af7d2ff-138b-5aa0-b3e8-9156e7970ed7","publicURL":"/static/b921f7cbc7765d764984833dc4860b02/python-design-patterns.png","childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABkUlEQVQoz41STU/CQBDtL/Pi0YOJ/8A/oQcPxhj/gmfjyY94w1tjEAyJsbGlpQRSCISSQmppgLbYj22f3SWtgEWdZLq7sztv3vQNh9SSJMl99ZxZUbxopc5tA/qtyOrdpueAEYkzPj/YFbHdZhz9hCnYxYOA46tnZLgkJgjDMH/oeR76/T4URWHnKIryYoQQdk+dsxwfJzcCdk8fsXN0Dc+8T2l8ot3WIIoiVFXFZDJBtVpFrVYDz/MMVJZlSJKERqMBQRDguu6y5VftA3vnt+BfLqG+nwGdfQSeAVFS0odvKJVKaLVaqFQqqNfrDKBcLjNwGqOFaNy27WXLrg/ImgQYB4B+CMyeEad906ROR8N0OmX7ZrMJ0zRZ4mw2w2AwgK7rmM/nLBYEwfc/pEKE5h0i+4md4jjOK1Ibj8d/ipEJxlQmcapy+p7QnITkyZRdr9fDaDRiK2VIWXW7XRiGgeFwCMuy1iaBS5bQDAhJjCQfjYSp7DgOA6aJtC3f91mMirBYLJivDXbREP9n3jZbzewLVNdEM3hydUUAAAAASUVORK5CYII=","aspectRatio":1.7777777777777777,"src":"/static/b921f7cbc7765d764984833dc4860b02/0823f/python-design-patterns.png","srcSet":"/static/b921f7cbc7765d764984833dc4860b02/c67b7/python-design-patterns.png 320w,\n/static/b921f7cbc7765d764984833dc4860b02/d3930/python-design-patterns.png 640w,\n/static/b921f7cbc7765d764984833dc4860b02/0823f/python-design-patterns.png 1280w,\n/static/b921f7cbc7765d764984833dc4860b02/c730b/python-design-patterns.png 1920w,\n/static/b921f7cbc7765d764984833dc4860b02/55bfe/python-design-patterns.png 2240w","sizes":"(max-width: 1280px) 100vw, 1280px"}}}},"timeToRead":8}},"pageContext":{"slug":"/python-design-patterns/","previous":{"fields":{"slug":"/como-me-organizo-para-estudar/"},"frontmatter":{"title":"Como me organizo para estudar?","date":"24 set, 2020"}},"next":{"fields":{"slug":"/js-design-patterns/"},"frontmatter":{"title":"Padrões de projeto com JavaScript","date":"01 out, 2020"}}}},"staticQueryHashes":["63159454"]}