Skip to content

Latest commit

 

History

History
143 lines (117 loc) · 4.94 KB

File metadata and controls

143 lines (117 loc) · 4.94 KB

Flyweight

O que é?

O Flyweight é um padrão estrutural que permite ajustar mais objetos na quantidade disponível de RAM compartilhando partes comuns de estado entre múltiplos objetos, em vez de manter todos os dados em cada objeto.

Quando usar?

  • Quando seu programa precisa gerar um grande número de objetos similares
  • Quando a RAM é uma restrição crítica no seu sistema
  • Quando muitos objetos compartilham propriedades comuns
  • Quando você pode extrair o estado intrínseco (compartilhado) do estado extrínseco (único)

Exemplo em Python

from typing import Dict
import json

# Flyweight
class Personagem:
    def __init__(self, nome: str, tipo: str, sprites: dict):
        # Estado intrínseco - compartilhado
        self.tipo = tipo
        self.sprites = sprites
        self.nome = nome
    
    def renderizar(self, x: int, y: int, estado: str):
        # Estado extrínseco - passado pelo contexto
        sprite = self.sprites.get(estado, "sprite_padrao")
        print(f"Renderizando {self.nome} ({self.tipo}) em x:{x}, y:{y} com sprite: {sprite}")

# FlyweightFactory
class FabricaPersonagens:
    _personagens: Dict[str, Personagem] = {}
    
    @classmethod
    def obter_personagem(cls, nome: str) -> Personagem:
        """Retorna um personagem existente ou cria um novo se necessário"""
        
        if nome not in cls._personagens:
            # Simulando carregamento de dados de um arquivo
            dados_personagem = {
                "guerreiro": {
                    "tipo": "guerreiro",
                    "sprites": {
                        "parado": "guerreiro_parado.png",
                        "correndo": "guerreiro_correndo.png",
                        "atacando": "guerreiro_atacando.png"
                    }
                },
                "arqueiro": {
                    "tipo": "arqueiro",
                    "sprites": {
                        "parado": "arqueiro_parado.png",
                        "correndo": "arqueiro_correndo.png",
                        "atacando": "arqueiro_atacando.png"
                    }
                },
                "mago": {
                    "tipo": "mago",
                    "sprites": {
                        "parado": "mago_parado.png",
                        "correndo": "mago_correndo.png",
                        "atacando": "mago_atacando.png"
                    }
                }
            }
            
            # Cria novo personagem apenas se necessário
            dados = dados_personagem.get(nome)
            if dados:
                cls._personagens[nome] = Personagem(
                    nome=nome,
                    tipo=dados["tipo"],
                    sprites=dados["sprites"]
                )
        
        return cls._personagens.get(nome)

# Contexto
class PersonagemContexto:
    def __init__(self, nome: str, x: int, y: int):
        # Estado extrínseco
        self.x = x
        self.y = y
        # Referência ao flyweight
        self.personagem = FabricaPersonagens.obter_personagem(nome)
    
    def mover(self, novo_x: int, novo_y: int):
        self.x = novo_x
        self.y = novo_y
        self.personagem.renderizar(self.x, self.y, "correndo")
    
    def atacar(self):
        self.personagem.renderizar(self.x, self.y, "atacando")

# Exemplo de uso
def main():
    # Criando múltiplas instâncias que compartilham dados
    personagem1 = PersonagemContexto("guerreiro", 10, 10)
    personagem2 = PersonagemContexto("guerreiro", 20, 20)
    personagem3 = PersonagemContexto("arqueiro", 30, 30)
    personagem4 = PersonagemContexto("mago", 40, 40)
    
    # Usando os personagens
    personagem1.mover(15, 15)
    personagem2.atacar()
    personagem3.mover(35, 35)
    personagem4.atacar()
    
    # Verificando o compartilhamento de recursos
    print("\nVerificando compartilhamento de recursos:")
    print(f"personagem1 e personagem2 compartilham o mesmo flyweight: "
          f"{personagem1.personagem is personagem2.personagem}")
    print(f"personagem1 e personagem3 compartilham o mesmo flyweight: "
          f"{personagem1.personagem is personagem3.personagem}")

if __name__ == "__main__":
    main()

Vantagens

  1. Economiza RAM quando o programa precisa de muitos objetos similares
  2. Centraliza o estado comum em um único lugar
  3. Reduz o custo de criação de objetos
  4. Melhora a coerência dos dados compartilhados

Desvantagens

  1. Pode complicar o código devido à separação de estado
  2. Pode impactar o tempo de execução ao trocar economia de RAM por CPU
  3. Requer identificação cuidadosa do que pode ser compartilhado
  4. Pode tornar o código mais difícil de manter

Considerações de Implementação

  • Identifique claramente os estados intrínseco e extrínseco
  • Use uma fábrica para gerenciar os flyweights
  • Considere usar cache para flyweights frequentemente usados
  • Avalie o trade-off entre memória e desempenho
  • Considere usar junto com o padrão Factory Method para criação de flyweights