<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Padrões de Projetos - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Aprenda a codificar - de graça. Tutoriais de programação em Python, JavaScript, Linux e muito mais. ]]>
        </description>
        <link>https://www.freecodecamp.org/portuguese/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Padrões de Projetos - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/portuguese/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 25 May 2026 04:46:53 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/portuguese/news/tag/padroes-de-projetos/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ 4 padrões de projeto que você deveria conhecer: Observer, Singleton, Strategy e Decorator ]]>
                </title>
                <description>
                    <![CDATA[ Você já esteve em uma equipe em que precisou começar um projeto do zero? Este é frequentemente o caso em muitas start-ups e outras pequenas empresas. Existem tantas linguagens de programação, arquiteturas e outras preocupações diferentes que pode ser difícil descobrir por onde começar. É aí que entram os padrões ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/4-padroes-de-projeto-que-voce-deveria-conhecer-observer-singleton-strategy-e-decorator/</link>
                <guid isPermaLink="false">63c6df5f91baea05fef70b67</guid>
                
                    <category>
                        <![CDATA[ Padrões de Projetos ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Marcelo Schäffer Petry ]]>
                </dc:creator>
                <pubDate>Thu, 01 Jun 2023 21:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2023/01/design-patterns.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/4-design-patterns-to-use-in-web-development/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">4 Design Patterns You Should Know for Web Development: Observer, Singleton, Strategy, and Decorator</a>
      </p><p><em>Você já esteve em uma equipe em que precisou começar um projeto do zero? Este é frequentemente o caso em muitas start-ups e outras pequenas empresas.</em></p><p>Existem tantas linguagens de programação, arquiteturas e outras preocupações diferentes que pode ser difícil descobrir por onde começar. É aí que entram os padrões de projeto.</p><p>Um padrão de projeto (do inglês, <em>design pattern</em>) é como um modelo para o seu projeto. Ele usa certas convenções e você pode esperar um tipo específico de comportamento dele. Esses padrões foram compostos de experiências de muitos desenvolvedores. Então, eles são realmente como diferentes conjuntos de melhores práticas.</p><p>Você e sua equipe decidem qual conjunto de melhores práticas é o mais útil para o seu projeto. Com base no padrão de projeto escolhido, todos vocês começarão a ter expectativas sobre o que o código deve fazer e sobre qual vocabulário usarão.</p><p>Os padrões de projeto de programação podem ser usados em todas as linguagens de programação e para se adequar a qualquer projeto, pois eles fornecem apenas um esboço geral de uma solução.</p><p>Existem 23 padrões oficiais no livro <em>Design Patterns - Elements of Reusable Object-Oriented Software</em>, que é considerado um dos livros mais influentes de teoria sobre a programação orientada a objetos e sobre desenvolvimento de software.</p><p>Neste artigo, abordarei quatro desses padrões de projeto para dar uma ideia do que são alguns dos padrões e quando você os usaria.</p><h2 id="o-padr-o-de-projeto-singleton"><strong>O padrão de projeto <em>Singleton</em></strong></h2><p>O padrão <em>singleton &nbsp;</em>permite que uma classe ou objeto tenha apenas uma instância e utilize uma variável global para armazenar essa instância. Você pode usar o carregamento lento (do inglês, <em>lazy loading</em>) para garantir que haja apenas uma instância da classe, pois ela só será criada quando você precisar.</p><p>Isso impede que múltiplas instâncias estejam ativas ao mesmo tempo, o que poderia causar bugs estranhos. Na maioria das vezes, isso é implementado no construtor. O objetivo do padrão <em>singleton </em>é, geralmente, regular o estado global de uma aplicação.</p><p>Um exemplo de <em>singleton </em>que você provavelmente usa o tempo todo é o seu log. Se você trabalha com alguns dos <em>frameworks </em>de <em>front-end</em>, como React ou Angular, sabe tudo sobre como pode ser difícil lidar com logs vindos de múltiplos componentes. Este é um ótimo exemplo de <em>singletons </em>em ação, pois você nunca quer mais de uma instância de um objeto de log, especialmente se estiver usando algum tipo de ferramenta de rastreamento de erros.</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class FoodLogger {
  constructor() {
    this.foodLog = []
  }
    
  log(order) {
    this.foodLog.push(order.foodItem)
    // faça um código elegante para enviar esse log para algum lugar
  }
}

// este é o singleton
class FoodLoggerSingleton {
  constructor() {
    if (!FoodLoggerSingleton.instance) {
      FoodLoggerSingleton.instance = new FoodLogger()
    }
  }
  
  getFoodLoggerInstance() {
    return FoodLoggerSingleton.instance
  }
}

module.exports = FoodLoggerSingleton</code></pre><figcaption>Um exemplo da classe <em>singleton</em></figcaption></figure><p>Agora, você não precisa se preocupar em perder logs de múltiplas instâncias, pois você só tem uma em seu projeto. Então, quando você quiser registrar o alimento que foi encomendado, pode usar a mesma instância de <em>FoodLogger </em>em múltiplos arquivos ou componentes.</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const FoodLogger = require('./FoodLogger')

const foodLogger = new FoodLogger().getFoodLoggerInstance()

class Customer {
  constructor(order) {
    this.price = order.price
    this.food = order.foodItem
    foodLogger.log(order)
  }
  
  // outras coisas legais acontecendo para o cliente
}

module.exports = Customer</code></pre><figcaption>Um exemplo de uma classe Customer usando o <em>singleton</em></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const FoodLogger = require('./FoodLogger')

const foodLogger = new FoodLogger().getFoodLoggerInstance()

class Restaurant {
  constructor(inventory) {
    this.quantity = inventory.count
    this.food = inventory.foodItem
    foodLogger.log(inventory)
  }
  
// outras coisas legais acontecendo no restaurante

module.exports = Restaurant</code></pre><figcaption>Um exemplo da classe Restaurant usando o mesmo <em>singleton </em>da classe Customer</figcaption></figure><p>Com esse padrão <em>singleton </em>instalado, você não precisa se preocupar apenas em obter os logs do arquivo principal da aplicação. Você pode obtê-los de qualquer lugar em sua base de código e todos eles vão exatamente para a mesma instância do <em>logger</em>, o que significa que nenhum de seus logs deve ser perdido devido a novas instâncias.</p><h2 id="o-padr-o-de-projeto-strategy"><strong>O padrão de projeto <em>Strategy</em></strong></h2><p>O padrão Strategy é como uma versão avançada de uma instrução "if else". É basicamente onde você cria uma interface para um método que você tem em sua classe base. Essa interface é usada para encontrar a implementação correta desse método que deve ser usado em uma classe derivada. A implementação, nesse caso, será decidida em tempo de execução com base no <em>client</em>.</p><p>O padrão Strategy é incrivelmente útil em situações em que você tem métodos obrigatórios e opcionais para uma classe. Algumas instâncias dessa classe não precisarão dos métodos opcionais e isso causa um problema para soluções de herança. Você poderia usar interfaces para os métodos opcionais, mas então teria que escrever a implementação toda vez que usasse essa classe, já que não haveria uma implementação padrão.</p><p>É aí que o padrão Strategy nos salva. Em vez do <em>client</em> procurar por uma implementação, ele delega para uma interface de Strategy e esta encontra a implementação correta. Um uso comum para isso é com sistemas de processamento de pagamentos.</p><p>Você poderia ter um carrinho de compras que só permite que os clientes finalizem a compra com cartões de crédito, mas perderia clientes que querem usar outros métodos de pagamento.</p><p>O padrão de projeto s<em>trategy </em>nos permite desacoplar os métodos de pagamento do processo de finalização da compra, o que significa que podemos adicionar ou atualizar estratégias sem alterar nenhum código no carrinho de compras ou no processo de finalização da compra.</p><p>Aqui está um exemplo de uma implementação do padrão <em>Strategy </em>usando o exemplo de método de pagamento.</p><figure class="kg-card kg-code-card"><pre><code class="language-typescript">class PaymentMethodStrategy {

  const customerInfoType = {
    country: string
    emailAddress: string
    name: string
    accountNumber?: number
    address?: string
    cardNumber?: number
    city?: string
    routingNumber?: number
    state?: string
  }
  
  static BankAccount(customerInfo: customerInfoType) {
    const { name, accountNumber, routingNumber } = customerInfo
    // faz coisas para receber o pagamento
  }
  
  static BitCoin(customerInfo: customerInfoType) {
    const { emailAddress, accountNumber } = customerInfo
    // faz coisas para receber o pagamento
  }
  
  static CreditCard(customerInfo: customerInfoType) {
    const { name, cardNumber, emailAddress } = customerInfo
    // faz coisas para receber o pagamento
  }
  
  static MailIn(customerInfo: customerInfoType) {
    const { name, address, city, state, country } = customerInfo
    // faz coisas para receber o pagamento
  }
  
  static PayPal(customerInfo: customerInfoType) {
    const { emailAddress } = customerInfo
    // faz coisas para receber o pagamento
  }
}</code></pre><figcaption>Um exemplo de implementação do padrão Strategy</figcaption></figure><p>Para implementar nosso método de pagamento de <em>Strategy</em>, criamos uma única classe com vários métodos estáticos. Cada método usa o mesmo parâmetro, <em>customerInfo</em>, e esse parâmetro tem um tipo definido de <em>customerInfoType</em> (viram só, vocês, desenvolvedores que usam TypeScript?). Observe que cada método tem sua própria implementação e usa valores diferentes de <em>customerInfo</em>.</p><p>Com o padrão <em>Strategy</em>, você também pode alterar dinamicamente a estratégia que está sendo usada no tempo de execução. Isso significa que você poderá alterar a estratégia ou implementação do método, sendo usado com base na entrada do usuário ou no ambiente em que a aplicação está sendo executada.</p><p>Você também pode definir uma implementação padrão em um arquivo <em>config.json</em> simples, como este:</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  "paymentMethod": {
    "strategy": "PayPal"
  }
}</code></pre><figcaption><em>config.json</em> para definir a implementação padrão de <em>paymentMethod </em>como "PayPal" no tempo de execução</figcaption></figure><p>Sempre que um cliente começar a fazer o <em>check-out</em> em seu site, o método de pagamento padrão que ele encontra é a implementação do PayPal que vem do <em>config.json</em>. Isso pode ser facilmente atualizado se o cliente selecionar um método de pagamento diferente.</p><p>Agora, vamos criar um arquivo para o nosso processo de <em>check-out</em>.</p><pre><code class="language-javascript">const PaymentMethodStrategy = require('./PaymentMethodStrategy')
const config = require('./config')

class Checkout {
  constructor(strategy='CreditCard') {
    this.strategy = PaymentMethodStrategy[strategy]
  }
  
  // faça algum código sofisticado aqui e obtenha a entrada do usuário e o método de pagamento
  
  changeStrategy(newStrategy) {
    this.strategy = PaymentMethodStrategy[newStrategy]
  }
  
  const userInput = {
    name: 'Malcolm',
    cardNumber: 3910000034581941,
    emailAddress: 'mac@gmailer.com',
    country: 'US'
  }
  
  const selectedStrategy = 'Bitcoin'
  
  changeStrategy(selectedStrategy)
  
  postPayment(userInput) {
    this.strategy(userInput)
  }
}

module.exports = new Checkout(config.paymentMethod.strategy)</code></pre><p>Essa classe <em>Checkout </em>é onde o padrão <em>Strategy</em> pode ser exibido. Importamos alguns arquivos para termos as estratégias de método de pagamento disponíveis e o padrão <em>Strategy</em> do <em>config</em>.</p><p>Em seguida, criamos a classe com o construtor e um valor de <em>fallback </em>para o padrão <em>Strategy</em> caso não haja um definido na configuração. Em seguida, atribuímos o valor de <em>Strategy</em> a uma variável de estado local.</p><p>Um método importante que precisamos implementar em nossa classe <em>Checkout </em>é a capacidade de alterar a estratégia de pagamento. Um cliente pode alterar o método de pagamento que deseja usar e você precisa ser capaz de lidar com isso. É para isso que serve o método <em>changeStrategy</em>.</p><p>Depois de fazer uma codificação sofisticada e obter todas as entradas de um cliente, você pode atualizar a estratégia de pagamento imediatamente com base na entrada e definir dinamicamente a variável <em>strategy </em>antes que o pagamento seja enviado para processamento.</p><p>Em algum momento, você pode precisar adicionar mais métodos de pagamento ao seu carrinho de compras e tudo o que você precisa fazer é adicioná-lo à classe <em>PaymentMethodStrategy</em>. Ele estará disponível instantaneamente em qualquer lugar em que a classe for usada.</p><p>O padrão de projeto <em>Strategy</em> é poderoso quando você está lidando com métodos que possuem múltiplas implementações. Pode parecer que você está usando uma interface, mas não precisa escrever uma implementação para o método toda vez que o chama em uma classe diferente. Ele oferece mais flexibilidade do que as interfaces.</p><h2 id="o-padr-o-de-projeto-observer"><strong>O padrão de projeto <em>Observer</em></strong></h2><p>Se você já usou o padrão MVC, você já usou o padrão de projeto <em>observer</em>. A parte do Modelo é semelhante ao "observado" e a parte da View é como um <em>observador </em>(do inglês, <em>observer) </em>do modelo. Seu modelo mantém todos os dados e o estado desses dados. Então, você tem os <em>observers</em>, como diferentes componentes, que vão pegar esses dados do observado quando os dados forem atualizados.</p><p>O objetivo do padrão de projeto <em>Observer</em> é criar essa relação de um para muitos entre o observado e todos os <em>observers</em> esperando por dados para que possam ser atualizados. Então, sempre que o estado do observado mudar, todos os <em>observers </em>serão notificados e atualizados instantaneamente.</p><p>Alguns exemplos de quando você usaria esse padrão incluem: envio de notificações de usuário, atualização, filtros e tratamento de assinantes.</p><p>Digamos que você tenha uma aplicação de página única com três listas suspensas de recursos, que dependem da seleção de uma categoria em uma lista suspensa de nível superior. Isso é comum em muitos sites de compras, como o <em>Home Depot</em>. Você tem vários filtros na página que dependem do valor de um filtro de nível superior.</p><p>O código para o menu suspenso de nível superior pode ser mais ou menos assim:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class CategoryDropdown {
  constructor() {
    this.categories = ['appliances', 'doors', 'tools']
    this.subscriber = []
  }
  
  // finja que há algum código sofisticado aqui
  
  subscribe(observer) {
    this.subscriber.push(observer)
  }
  
  onChange(selectedCategory) {
    this.subscriber.forEach(observer =&gt; observer.update(selectedCategory))
  }
}</code></pre><figcaption>O assunto que atualiza os <em>observers</em></figcaption></figure><p>Este arquivo <em>CategoryDropdown </em>é uma classe simples com um construtor que inicializa as opções de categoria disponíveis no menu suspenso. Este é o arquivo que você usaria para recuperar uma lista do <em>back-end</em> ou qualquer tipo de classificação que deseja fazer antes que o usuário veja as opções.</p><p>O método <em>subscribe</em> é como cada filtro criado com essa classe receberá atualizações sobre o estado do <em>Observer</em>.</p><p>O método <em>onChange </em>é como enviamos uma notificação a todos os assinantes de que uma mudança de estado ocorreu no <em>Observer</em> que eles estão olhando. Apenas percorremos todos os assinantes e chamamos seu método de atualização com a categoria <em>selectedCategory</em>.</p><p>O código para os outros filtros pode parecer algo assim:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class FilterDropdown {
  constructor(filterType) {
    this.filterType = filterType
    this.items = []
  }
  
  // mais código elegante aqui; talvez faça a chamada da API para obter a lista de itens baseada no filterType
  
  update(category) {
    fetch('https://example.com')
      .then(res =&gt; this.items(res))
  }
}</code></pre><figcaption>Um potencial <em>Observer</em> do observado.</figcaption></figure><p>Esse arquivo <em>FilterDropdown </em>é outra classe simples que representa todos os possíveis menus suspensos que podemos usar em uma página. Quando uma nova instância dessa classe é criada, ela precisa receber um <em>filterType</em>. Isso pode ser usado para fazer chamadas de API específicas para obter a lista de itens.</p><p>O método <code>update</code> é uma implementação do que você pode fazer com a nova categoria depois que ela foi enviada pelo <em>Observer</em>.</p><p>Agora, veremos o que significa usar esses arquivos com o padrão <em>Observer</em>:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const CategoryDropdown = require('./CategoryDropdown')
const FilterDropdown = require('./FilterDropdown')

const categoryDropdown = new CategoryDropdown() 

const colorsDropdown = new FilterDropdown('colors')
const priceDropdown = new FilterDropdown('price')
const brandDropdown = new FilterDropdown('brand')

categoryDropdown.subscribe(colorsDropdown)
categoryDropdown.subscribe(priceDropdown)
categoryDropdown.subscribe(brandDropdown)</code></pre><figcaption>Um exemplo do padrão <em>Observer</em> em ação</figcaption></figure><p>O que este arquivo nos mostra é que temos 3 menus suspensos que são assinantes da categoria <em>drop-down</em> observável. Em seguida, assinamos cada um desses <em>drop-downs</em> para o <em>Observer</em>. Sempre que a categoria do <em>Observer </em>for atualizada, ele enviará o valor para cada assinante, o que atualizará as listas de <em>drop-down</em> individuais instantaneamente.</p><h2 id="o-padr-o-de-projeto-decorator"><strong>O padrão de projeto <em>Decorator</em></strong></h2><p>Usar o padrão de projeto <em>Decorator </em>é bastante simples. Você pode ter uma classe base com métodos e propriedades que estão presentes quando você cria um objeto com a classe. Agora, digamos que você tenha algumas instâncias da classe que precisam de métodos ou propriedades que não vieram da classe base.</p><p>Você pode adicionar esses métodos e propriedades extras à classe base, mas isso poderia estragar suas outras instâncias. Você poderia até criar subclasses para conter métodos e propriedades específicos que você precisa e que não pode colocar na sua classe base.</p><p>Qualquer uma dessas abordagens resolverá o seu problema, mas são desajeitadas e ineficientes. É aí que entra o padrão <em>Decorator</em>. Em vez de deixar o seu código base feio só para adicionar algumas coisas a uma instância de objeto, você pode colar essas coisas específicas diretamente na instância.</p><p>Então, se você precisar adicionar uma nova propriedade que contenha o preço de um objeto, você pode usar o padrão <em>decorator </em>para adicioná-lo diretamente a essa instância de objeto particular e isso não afetará qualquer outra instância desse objeto de classe.</p><p>Você já comprou comida <em>on-line</em>? Então, provavelmente, já encontrou o padrão <em>Decorator</em>. Se você estiver pegando um sanduíche e quiser adicionar coberturas especiais, o site não está adicionando essas coberturas a todas as instâncias de sanduíche que os usuários estão tentando pedir.</p><p>Aqui está um exemplo de uma classe de cliente:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class Customer {
  constructor(balance=20) {
    this.balance = balance
    this.foodItems = []
  }
  
  buy(food) {
    if (food.price) &lt; this.balance {
      console.log('you should get it')
      this.balance -= food.price
      this.foodItems.push(food)
    }
    else {
      console.log('maybe you should get something else')
    }
  }
}

module.exports = Customer</code></pre><figcaption>Exemplo de classe de cliente (customer)</figcaption></figure><p>Aqui está um exemplo de uma classe de sanduíche:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">class Sandwich {
  constructor(type, price) {
    this.type = type
    this.price = price
  }
  
  order() {
    console.log(`Você pediu um sanduíche de ${this.type} no valor de $ ${this.price}.`)
  }
}

class DeluxeSandwich {
  constructor(baseSandwich) {
    this.type = `${baseSandwich.type} deluxe`
    this.price = baseSandwich.price + 1.75
  }
}

class ExquisiteSandwich {
  constructor(baseSandwich) {
    this.type = `${baseSandwich.type} delicioso`
    this.price = baseSandwich.price + 10.75
  }
  
  order() {
    console.log(`Você pediu um sanduíche ${this.type}. Ele tem o que você precisa para ficar feliz por dias.`)
  }
}

module.exports = { Sandwich, DeluxeSandwich, ExquisiteSandwich }</code></pre><figcaption>Exemplo de classe de sanduíche</figcaption></figure><p>A classe de sanduíche é onde o padrão <em>Decorator </em>é usado. Temos uma classe base <em>Sandwich </em>que estabelece as regras para o que acontece quando um sanduíche regular é encomendado. Os clientes podem querer atualizar os sanduíches e isso significa apenas uma mudança de ingredientes e preço.</p><p>Você só queria adicionar a funcionalidade de aumentar o preço e atualizar o tipo de sanduíche para o <em>DeluxeSandwich </em>sem mudar como é encomendado. Embora possa ser necessário um método de pedido diferente para o <em>ExquisiteSandwich </em>devido à mudança drástica na qualidade dos ingredientes.</p><p>O padrão <em>decorator </em>permite que você altere dinamicamente a classe base sem afetá-la ou a qualquer outra classe. Você não precisa se preocupar em implementar funções que não sabe, como com interfaces, e não precisa incluir propriedades que não usará em todas as classes.</p><p>Agora, vamos passar por um exemplo onde essa classe é instanciada como se um cliente estivesse fazendo um pedido de sanduíche.</p><pre><code class="language-javascript">const { Sandwich, DeluxeSandwich, ExquisiteSandwich } = require('./Sandwich')
const Customer = require('./Customer')

const cust1 = new Customer(57)

const turkeySandwich = new Sandwich('Peru', 6.49)
const bltSandwich = new Sandwich('Bacon, alface e tomate', 7.55)

const deluxeBltSandwich = new DeluxeSandwich(bltSandwich)
const exquisiteTurkeySandwich = new ExquisiteSandwich(turkeySandwich)

cust1.buy(turkeySandwich)
cust1.buy(bltSandwich)</code></pre><h2 id="considera-es-finais"><strong>Considerações finais</strong></h2><p>Eu costumava achar que os padrões de projeto eram essas orientações de desenvolvimento de software loucas e distantes. Mais tarde, descobri que os utilizo o tempo todo!</p><p>Alguns dos padrões que abordei são usados em tantas aplicações que fariam sua cabeça girar. Eles são apenas teoria no fim das contas. Cabe a nós, desenvolvedores, usar essa teoria de maneiras que tornem nossas aplicações fáceis de implementar e de manter.</p><p>Você já usou algum dos outros padrões de projeto em seus projetos? A maioria dos lugares geralmente escolhe um padrão de projeto e adere a ele. Então, gostaria de ouvir de vocês sobre os padrões que vocês usam.</p><p>Obrigado pela leitura.</p><p></p><p>Siga a autora no <a href="https://twitter.com/FlippedCoding">Twitter</a>, onde ela publica sobre coisas úteis e/ou divertidas.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Os 3 tipos de padrões de projetos que todo desenvolvedor deveria conhecer (com exemplos de código de cada um) ]]>
                </title>
                <description>
                    <![CDATA[ O que é um padrão de projeto? Padrões de projeto são soluções em nível de design para problemas recorrentes que os engenheiros de software encontram com frequência. Não são código - repito, ❌CÓDIGO. Eles são como uma descrição de como lidar com esses problemas e projetar uma solução. Usar esses ]]>
                </description>
                <link>https://www.freecodecamp.org/portuguese/news/os-3-tipos-de-padroes-de-projetos-que-todo-desenvolvedor-deveria-conhecer-com-exemplos-de-codigo-de-cada-um/</link>
                <guid isPermaLink="false">61fe6d9253557304fa19f656</guid>
                
                    <category>
                        <![CDATA[ Padrões de Projetos ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Rosa ]]>
                </dc:creator>
                <pubDate>Mon, 07 Feb 2022 23:53:54 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/design-patterns-everywhere.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artigo original:</strong> <a href="https://www.freecodecamp.org/news/the-basic-design-patterns-all-developers-need-to-know/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">The 3 Types of Design Patterns All Developers Should Know (with code examples of each)</a>
      </p><h2 id="o-que-um-padr-o-de-projeto">O que é um padrão de projeto?</h2><p>Padrões de projeto são soluções em nível de design para problemas recorrentes que os engenheiros de software encontram com frequência. Não são código - repito,<strong><strong><strong><strong> </strong></strong></strong></strong>❌<strong><strong><strong><strong>C</strong></strong></strong>ÓDIGO</strong>. Eles são como uma descrição de como lidar com esses problemas e projetar uma solução.</p><p>Usar esses padrões é considerado uma boa prática, já que o projeto da solução foi testado muitas vezes e com sucesso, resultando em maior legibilidade do código final. Padrões de projetos são, com frequência, criados para linguagens de POO (Programação Orientada a Objetos), como o Java, e usadas por elas. Será em Java que escreveremos os exemplos que daremos daqui até o final do texto.</p><h2 id="tipos-de-padr-es-de-projetos"><strong>Tipos de padrões de projetos</strong></h2><p>Existem cerca de 26 padrões descobertos atualmente (não acho que tratarei de todos eles).</p><p>Esses 26 podem ser classificados em 3 tipos:</p><p>1. Criacionais: esses padrões foram criados para a instanciação de classes. Eles podem tanto ser padrões de criação de classes como de criação de objetos.</p><p>2. Estruturais: esses padrões foram criados levando em conta a estrutura de uma classe e sua composição. O objetivo principal da maioria desses padrões é aumentar a funcionalidade das classes envolvidas, sem alterar muito de sua composição.</p><p>3. Comportamentais: esses padrões foram criados levando em conta a forma como uma classe se comunica com as outras.</p><p>Neste artigo, examinarei um padrão de projeto básico para cada tipo classificado.</p><h2 id="tipo-1-criacional-o-padr-o-de-projeto-singleton"><strong>Tipo 1: Criacional – o padrão de projeto Singleton</strong></h2><p>O padrão de projeto Singleton é um padrão criacional, cujo objetivo é criar apenas uma instância de uma classe e fornecer apenas um ponto global de acesso àquele objeto. Um exemplo comumente usado dessa classe em Java é o calendário, onde você não pode fazer uma instância daquela classe. Ele também usa seu próprio método <code>getInstance()</code>para obter o objeto a ser usado.</p><p>Uma classe usando o padrão de projeto Singleton incluirá,</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/singleton-class-diagram.png" class="kg-image" alt="singleton-class-diagram" width="276" height="196" loading="lazy"><figcaption>Diagrama da classe Singleton</figcaption></figure><ol><li>Uma variável estática privada, que contém a única instância da classe.</li><li>Um construtor privado, de modo a não ser possível instanciá-la de qualquer outro lugar.</li><li>Um método estático público, para retornar a instância única da classe.</li></ol><p>Há muitas implementações diferentes do padrão Singleton. Hoje, examinarei as implementações:</p><p>1. Instanciação ávida</p><p>2. Instanciação preguiçosa</p><p>3. Instanciação thread-safe</p><h3 id="a-vida-eager-"><strong>A ávida (Eager)</strong></h3><pre><code class="language-java">public class EagerSingleton {
	// cria uma instância da classe.
	private static EagerSingleton instance = new EagerSingleton();

	// construtor privado, para que ela não possa ser instanciada fora da classe.
	private EagerSingleton() {  }

	// obtém a única instância criada do objeto.
	public static EagerSingleton getInstance() {
		return instance;
	}
}</code></pre><p>Esse tipo de instanciação acontece durante o carregamento da classe, já que a instância da variável acontece fora de qualquer método. Isso impõe uma desvantagem substancial se essa classe não for usada pela aplicação do client. O plano de contingência, se essa classe não for usada, é a instanciação preguiçosa.</p><h3 id="a-pregui-osa-lazy-"><strong>A preguiçosa (Lazy)</strong></h3><p>Não há muita diferença com relação à implementação acima. As principais diferenças estão na variável estática, que inicialmente é declarada como null (nula), e no fato de que ela é instanciada apenas dentro do método <code>getInstance()</code> se e somente se a variável de instância permanecer null (nula) no momento da verificação.</p><pre><code class="language-java">public class LazySingleton {
	// inicializa a instância como null.
	private static LazySingleton instance = null;

	// construtor privado, para que ela não possa ser instanciada fora da classe.
	private LazySingleton() {  }

	// verifica se a instância é null. Se estiver, o objeto é criado.
	public static LazySingleton getInstance() {
		if (instance == null) {
			instance = new LazySingleton();
		}
		return instance;
	}
}</code></pre><p>Isso conserta um problema, mas ainda existe outro. E se dois clients diferentes acessarem a classe Singleton ao mesmo tempo? Bem, elas verificarão se a instância está null ao mesmo tempo, verão que isso é verdade e criarão duas instâncias da classe para cada solicitação feita pelos dois clients. Para resolver isso, a instanciação Thread Safe deve ser implementada.</p><h3 id="a-seguran-a-da-thread-fundamental"><strong>A segurança (da thread) é fundamental</strong></h3><p>Em Java, a palavra-chave synchronized é usada nos métodos ou nos objetos para implementar a segurança das threads, de modo que apenas uma thread acesse um recurso específico em determinado momento. A instanciação da classe é colocada dentro de um bloco <em>synchronized</em> para que o método somente possa ser acessado por um client de cada vez.</p><pre><code class="language-java">public class ThreadSafeSingleton {
	// inicializa a instância como null.
	private static ThreadSafeSingleton instance = null;

	// construtor privado, para que ela não possa ser instanciada fora da classe.
	private ThreadSafeSingleton() {  }

	// verifica se a instância é null dentro de um bloco synchronized. Se for, o objeto é criado
	public static ThreadSafeSingleton getInstance() {
		synchronized (ThreadSafeSingleton.class) {
			if (instance == null) {
				instance = new ThreadSafeSingleton();
			}
		}
		return instance;
	}
}</code></pre><p>A sobrecarga de um método <em>synchronized</em> é alta, reduzindo o desempenho de toda a operação.</p><p>Por exemplo, se a variável de instância já tiver sido instanciada, cada vez que algum client acessar o método <code>getInstance()</code>, o método <code>synchronized</code> é executado e há uma queda de desempenho. Isso acontece apenas para verificar se o valor da variável <code>instance</code> é null. Se descobrir que é, ele sai do método.</p><p>Para reduzir essa sobrecarga, é usado o <em>double locking</em>. A verificação é usada antes do método <code>synchronized</code> também. Somente se o valor for null o método <code>synchronized</code> é executado.</p><pre><code class="language-java">// double locking é usado para reduzir a sobrecarga do método synchronized
public static ThreadSafeSingleton getInstanceDoubleLocking() {
	if (instance == null) {
		synchronized (ThreadSafeSingleton.class) {
			if (instance == null) {
				instance = new ThreadSafeSingleton();
			}
		}
	}
	return instance;
}</code></pre><p>Sigamos para a próxima classificação.</p><h2 id="tipo-2-estrutural-o-padr-o-de-projeto-decorator"><strong>Tipo 2: estrutural - o padrão de projeto Decorator</strong></h2><p>Permitam-me apresentar para vocês um pequeno cenário para contextualizar melhor o motivo e as situações nas quais devemos usar o padrão Decorator.</p><p>Digamos que você tenha um café e, como qualquer iniciante, você começa com apenas dois tipos de café normal, o da casa e o escuro torrado. Em seu sistema de cobrança, havia uma classe para cada um dos tipos de café, os quais herdam da classe abstrata bebida. A clientela começa a aparecer e a tomar seu maravilhoso (ainda que um tanto amargo) café. Há, porém, aqueles novatos do café, que, Deus me livre!!!, querem tomar café com açúcar ou leite. Nem parece mais café!</p><p>Agora, você precisa desses dois adicionais, no menu e, infelizmente, no sistema de cobrança. Originalmente, seu funcionário da TI criará uma subclasse para os dois cafés, um para o café com açúcar e outro para o café com leite. Então, como o cliente tem sempre razão, alguma hora aparecerá um que diga aquelas palavras pavorosas:</p><p><em>"Poderia me dar um café com leite e açúcar<em><em><em><em><em>, </em></em></em></em></em>por favor<em><em><em><em><em>?</em></em></em></em></em>"</em></p><h3 id=""><strong>???</strong></h3><p>Lá vai seu sistema de cobrança rir da sua cara novamente. Bem, de volta à prancheta de desenhos…</p><p>O funcionário da TI adiciona café com leite e açúcar para cada classe pai de café. O resto do mês é tranquilo, as pessoas fazem fila para tomar o seu café, e você até está fazendo dinheiro. ??</p><p>Mas espere, tem mais!</p><p>O mundo vai contra você novamente. A concorrência abre um café do outro lado da rua, não apenas com 4 tipos de café, mas com 10 adicionais! ?</p><p>Você compra tudo isso e muito mais para poder vender um café melhor no seu estabelecimento, e é aí que você se lembra de que não atualizou o maldito sistema de cobrança. Possivelmente, você não conseguirá fazer o número infinito de subclasses para toda e qualquer combinação dos adicionais com os novos tipos de café também. Isso para não falar do tamanho final que o sistema terá.??</p><p>Está na hora de investir, de fato, em um sistema de cobrança adequado. Você encontra uma nova equipe de TI, que saiba de verdade o que está fazendo, e eles dizem:</p><p><em>"Bem<em><em><em><em><em>, </em></em></em></em></em>isso fica muito mais fácil e menor se usarmos o padrão D<em><em><em><em><em>ecorator.</em></em></em></em></em>"</em></p><h3 id="mas-que-diabos-isso"><strong>Mas que diabos é isso?</strong></h3><p>O padrão de projetos Decorator está na categoria estrutural de uma classe, seja por herança, composição ou ambos. O objetivo desse padrão é modificar a funcionalidade de um objeto em tempo de execução. Esse é um dos vários padrões de projetos que usam classes abstratas e interfaces com composição para obter o resultado desejado.</p><p>Vamos dar uma chance à matemática (medo!) e colocar isso em perspectiva:</p><p>Imagine 4 tipos de café e 10 complementos. Se ficarmos na criação de subclasses para cada combinação diferente de todos os adicionais para um tipo de café, teremos:</p><p>(10–1)² = 9² = 81 subclasses</p><p>Subtraímos 1 de 10, já que não podemos combinar um adicional com outro do mesmo tipo (açúcar com açúcar parece estúpido). E isso para um único tipo de café. Multiplique esses <strong><strong><strong><strong>81 </strong></strong></strong>por<strong><strong><strong> 4</strong></strong></strong></strong> e você chega a incríveis <strong><strong><strong><strong>324</strong></strong></strong></strong> subclasses diferentes! Que tal codificar isso tudo?</p><p>Porém, com o padrão Decorator, serão necessárias apenas 16 classes para esse cenário. Quer apostar?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/decorator-class-diagram.png" class="kg-image" alt="decorator-class-diagram" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/decorator-class-diagram.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/decorator-class-diagram.png 624w" width="624" height="343" loading="lazy"><figcaption>Diagrama de classe do padrão de projeto Decorator</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/decorator-coffee-class-diagram.png" class="kg-image" alt="decorator-coffee-class-diagram" srcset="https://www.freecodecamp.org/portuguese/news/content/images/size/w600/2022/02/decorator-coffee-class-diagram.png 600w, https://www.freecodecamp.org/portuguese/news/content/images/2022/02/decorator-coffee-class-diagram.png 691w" width="691" height="397" loading="lazy"><figcaption>Diagrama de classe de acordo com o cenário do café</figcaption></figure><p>Se mapearmos nosso cenário de acordo com o diagrama de classes acima, temos 4 classes para os quatro tipos de café, 10 para cada adicional, 1 para o componente abstrato e mais 1 para o Decorator abstrato. Viram? 16! Agora, me entreguem os $100 dólares da aposta (brincadeira, mas eu não recusaria se me oferecessem…)</p><p>Como você pode ver acima, da mesma forma que os tipos concretos de café são subclasses da classe abstrata <em>Beverage</em> (bebida), a classe abstrata <em>AddOn</em> (adicional) também herda seus métodos dela. Os adicionais, que são suas subclasses, por sua vez, herdam todos os novos métodos para acrescentar funcionalidade ao objeto base quando necessário.</p><p>Vamos olhar para o código para ver esse padrão em uso.</p><p>Primeiro, tornamos a classe <em>Beverage</em> abstrata. É dela que todos os tipos de café herdarão:</p><pre><code class="language-java">public abstract class Beverage {
	private String description;
    
	public Beverage(String description) {
		super();
		this.description = description;
	}
    
	public String getDescription() {
		return description;
	}
    
	public abstract double cost();
}</code></pre><p>Em seguida, adicionamos as classes dos tipos de café concretos:</p><pre><code class="language-java">public class HouseBlend extends Beverage {
	public HouseBlend() {
		super(“House blend”);
	}

	@Override
	public double cost() {
		return 250;
	}
}

public class DarkRoast extends Beverage {
	public DarkRoast() {
		super(“Dark roast”);
	}

	@Override
	public double cost() {
		return 300;
	}
}</code></pre><p>A classe abstrata <em>AddOn </em>também herdará da classe abstrata <em>Beverage</em> (mais sobre isso abaixo).</p><pre><code class="language-java">public abstract class AddOn extends Beverage {
	protected Beverage beverage;

	public AddOn(String description, Beverage bev) {
		super(description);
		this.beverage = bev;
	}

	public abstract String getDescription();
}</code></pre><p>E agora, as implementações concretas dessa classe abstrata:</p><pre><code class="language-java">public class Sugar extends AddOn {
	public Sugar(Beverage bev) {
		super(“Sugar”, bev);
	}

	@Override
	public String getDescription() {
		return beverage.getDescription() + “ with Mocha”;
	}

	@Override
	public double cost() {
		return beverage.cost() + 50;
	}
}

public class Milk extends AddOn {
	public Milk(Beverage bev) {
		super(“Milk”, bev);
	}

	@Override
	public String getDescription() {
		return beverage.getDescription() + “ with Milk”;
	}

	@Override  public double cost() {
		return beverage.cost() + 100;
	}
}</code></pre><p>Como você pode ver acima, podemos passar qualquer subclasse de <em>Beverage</em> para qualquer subclasse de <em>AddOn</em>, e obter o custo adicional, assim como a descrição atualizada. Como a classe <em>AddOn</em> é, essencialmente, do tipo <em>Beverage</em>, podemos passar um<em> AddOn</em> em outro <em>AddOn</em>. Dessa forma, podemos acrescentar o número de adicionais que quisermos a um tipo específico de café.</p><p>Vamos escrever o código para testar isso:</p><pre><code class="language-java">public class CoffeeShop {
	public static void main(String[] args) {
		HouseBlend houseblend = new HouseBlend();
		System.out.println(houseblend.getDescription() + “: “ + houseblend.cost());

		Milk milkAddOn = new Milk(houseblend);
		System.out.println(milkAddOn.getDescription() + “: “ + milkAddOn.cost());

		Sugar sugarAddOn = new Sugar(milkAddOn);
		System.out.println(sugarAddOn.getDescription() + “: “ + sugarAddOn.cost());
	}
}</code></pre><p>O resultado final é:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/decorator-final.png" class="kg-image" alt="decorator-final" width="323" height="88" loading="lazy"><figcaption>Calma! Esse valor é em rúpias do Sri Lanka!</figcaption></figure><p>Funcionou! Conseguimos acrescentar mais de um adicional a um tipo de café e atualizamos com sucesso seu preço final e sua descrição. Vejam que não foi necessário fazer subclasses infinitas para cada combinação de adicional para todos os tipos de café.</p><p>Chegamos, finalmente, à última categoria.</p><h2 id="tipo-3-comportamental-o-padr-o-de-projeto-command"><strong>Tipo 3: Comportamental - o padrão de projeto Command</strong></h2><p>O padrão de projeto comportamental tem como foco a maneira como as classes e objetos se comunicam uns com os outros. A ideia central do padrão Command é produzir um maior nível de acoplamento fraco entre as partes envolvidas (leia-se as classes).</p><p><em>Hã<em><em><em><em><em>… </em></em></em></em></em>o que é isso<em><em><em><em><em>?</em></em></em></em></em></em></p><p>Acoplamento é a maneira pela qual duas classes (ou mais) interagem umas com as outras. O cenário ideal é quando essas classes interagem sem depender fortemente umas das outras. Esse é o acoplamento fraco. Então, uma definição melhor para o acoplamento fraco seria "classes interconectadas, mas fazendo o menor uso possível umas das outras".</p><p>A necessidade desse padrão surgiu quando solicitações precisavam ser enviadas sem que se soubesse conscientemente o que estava sendo solicitado ou quem era o receptor da solicitação.</p><p>Neste padrão, a classe que o chama é desacoplada da classe que, de fato, realiza a ação. A classe que chama tem apenas o método de execução para chamar, que executa o comando necessário quando o <em>client</em> o solicita.</p><p>Vamos usar um exemplo do mundo real, pedir um prato em um restaurante elegante. O fluxo é: você faz o pedido (comando) ao garçom (quem "invoca" o pedido), que o entregará ao chef (receptor do pedido), para que você possa receber o alimento. Pode parecer simples… mas é um pouco complicado de codificar.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/chain-of-command-be-like-pop-snoke-im-going-to-27790631.png" class="kg-image" alt="chain-of-command-be-like-pop-snoke-im-going-to-27790631" width="500" height="375" loading="lazy"></figure><p>A ideia, de fato, é simples. A codificação, no entanto, é um pouco mais difícil.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/portuguese/news/content/images/2022/02/command-class-diagram.png" class="kg-image" alt="command-class-diagram" width="529" height="526" loading="lazy"><figcaption>Diagrama de classes do padrão Command</figcaption></figure><p>O fluxo da operação do lado técnico é: você faz um comando concreto, que implementa a interface Command, pedindo que o receptor realize uma ação e envia o comando a quem invoca o pedido. Essa é a pessoa que sabe a quem dar esse comando. O chef é o único que sabe o que fazer com o comando/pedido específico. Assim, quando o método "execute" daquele que invoca o pedido é executado, ele, por sua vez, faz com que o método execute dos objetos de comando seja passado ao receptor, completando assim as ações necessárias.</p><h3 id="o-que-precisamos-implementar-"><strong>O que precisamos implementar:</strong></h3><ol><li>Uma interface Command</li><li>Uma classe Order (pedido) que implementa a interface Command</li><li>Uma classe Waiter (Garçom, quem invoca o pedido)</li><li>Uma classe Chef (o receptor)</li></ol><p>Desse modo, o código terá a seguinte aparência:</p><h3 id="chef-o-receptor"><strong>Chef, o receptor</strong></h3><pre><code class="language-java">public class Chef {
	public void cookPasta() {
		System.out.println(“O Chef está fazendo massa ao molho Alfredo…”);
	}

	public void bakeCake() {
		System.out.println(“O Chef está fazendo um bolo de chocolate…”);
	}
}</code></pre><h3 id="command-a-interface"><strong>Command, a interface</strong></h3><pre><code class="language-java">public interface Command {
	public abstract void execute();
}</code></pre><h3 id="order-pedido-o-comando-concreto"><strong>Order (pedido), o comando concreto</strong></h3><pre><code class="language-java">public class Order implements Command {
	private Chef chef;
	private String food;

	public Order(Chef chef, String food) {
		this.chef = chef;
		this.food = food;
	}

	@Override
	public void execute() {
		if (this.food.equals(“Massa”)) {
			this.chef.cookPasta();
		} else {
			this.chef.bakeCake();
		}
	}
}</code></pre><h3 id="waiter-gar-om-quem-invoca-o-pedido"><strong>Waiter, (Garçom) quem invoca o pedido</strong></h3><pre><code class="language-java">public class Waiter {
	private Order order;

	public Waiter(Order ord) {
		this.order = ord;
	}

	public void execute() {
		this.order.execute();
	}
}</code></pre><h2 id="voc-o-cliente"><strong>Você, o cliente</strong></h2><pre><code class="language-java">public class Client {
	public static void main(String[] args) {
		Chef chef = new Chef();
        
		Order order = new Order(chef, “Massa”);
		Waiter waiter = new Waiter(order);
		waiter.execute();

		order = new Order(chef, “Bolo”);
		waiter = new Waiter(order);
		waiter.execute();
	}
}</code></pre><p>Como podemos ver acima, Client faz um Order (pedido) e define o Receiver (Receptor) como sendo o Chef. Order é enviado ao Waiter (Garçom), que saberá quem deve executar o pedido (ou seja, quando dar ao chefe o pedido para que ele o faça). Quando quem invoca o pedido é executado, o método execute de Order é executado no receptor (ou seja, o chef recebe o comando para cozinhar a massa ou para assar o bolo).</p><h2 id="recapitulando"><strong>Recapitulando</strong></h2><p>Neste artigo, vimos:</p><ol><li>O que de fato é um padrão de projetos,</li><li>Os diferentes tipos de padrão de projetos e o motivo de serem diferentes</li><li>Um padrão de projetos básico ou comum de padrão de projetos para cada tipo</li></ol><p>Espero que isso tenha sido útil.</p><p>Encontre o repositório do código para este artigo <a href="https://github.com/samsam-026/Design_Patterns">aqui</a>.</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
