Algumas aplicações, tais como editores de texto, possuem uma granularidade de representação muito fina sobre os dados;... e uma quantidade muito grande de dados. O custo de memória para representação destes dados individualmente pode ser proibitivo. Na maioria dos casos uma mesma representação é replicada em muitos objetos ao mesmo tempo. Portanto, ocorre muita repetição de representação de objetos. O padrão flyweight é solução para o problema. Este padrão permite compartilhar representações (ou estados) para objetos diferentes. 29-abr-09 Leandro Tonietto 137
Independência dos objetos-pai. Flyweight é um objeto que representa um estado qualquer e é independe de contexto, podendo ser referenciado por diversos tipos de elementos ou outros objetos. Para tanto, ele não pode fazer referência ou estar atrelado a um tipo específico de objeto-pai. Conceito: Estado intrínseco ou extrínseco. Intrínseco: os dados são independentes do contexto. Extrínseco: dependentes ou variam conforme o contexto. Portanto, não podem ser compartilhados. É possível que o contexto seja passado por parâmetro para alguma operação do flyweight. 29-abr-09 Leandro Tonietto 138
Exemplo em [1]. Representação de elementos de texto: Um texto contém colunas, que contêm parágrafos, que contém os caracteres. Diversos estados dos caracteres são repetidos em diversos pontos do texto 29-abr-09 Leandro Tonietto 139
Compartilhamento de objetos para diminuir consumo de memória Por questões de economia de memória, os objetos que representação caracteres e suas formatações, são compartilhados por diversos outros objetos. 29-abr-09 Leandro Tonietto 140
Estrutura que representa o exemplo em [1]: Por exemplo, o objeto Flyweight pode armazenar apenas as informações referentes ao caractere e o contexto de uso é passado pelo objeto-pai Row, como: posição em que a letra deve ser desenhada. A Economia está no fato de que representações diferentes é muito menor que o número de objetos ou elementos num texto. 29-abr-09 Leandro Tonietto 141
Estrutura básica: Structural Patterns - Flyweight 29-abr-09 Leandro Tonietto 142
Aplicabilidade: Structural Patterns - Flyweight Aplicações que usam um grande número de objetos. Custo de armazenamento é alto por conta quantidade de representação de objetos. Muitos objetos podem compartilhar uma mesma representação e é possível separar o estado extrínseco dos mesmos. Ponto de atenção: Objetos conceitualmente distintos, tem uma mesma identidade. 29-abr-09 Leandro Tonietto 143
Conseqüências: Custos de execução para computação do estado extrínseco (procura, transferência, computação,...) Ganhos de armazenamento dependem: Redução do número de instâncias com o compartilhamento. Quantidade de estado intrínseco por objeto. Dados extrínsecos armazenados ou computados. Quanto mais estados são compartilhados, menor o custo de memória. Quanto mais os estados extrínsecos puderem ser calculados do que armazenados, melhor. Exemplo, a posição de caractere no texto: não é necessário que ela seja armazenada, uma vez que o texto é seqüencial e os caracteres podem ser renderizados desta forma. Em [1]: Then you save on storage in two ways: Sharing reduces the cost of intrinsic state, and you trade extrinsic state for computation time. Há ainda a questão de objetos conceitualmente diferentes compartilharem a mesma memória, deve-se ter atenção para que somente o estado intrínseco esteja de fato armazenado no flyweight. 29-abr-09 Leandro Tonietto 144
Implementação: Ponto-chave está na separação entre o que é extrínseco do que intrínseco. Isto depende da aplicação em questão. Devido ao compartilhamento de estados, não é interessante que o cliente instancie diretamente os flyweight, neste caso é melhor terceirizar esta tarefa para uma fábrica, que pode decidir entre criar um flyweight ou retornar um já criado. Também há um ponto de atenção na remoção de objetos da memória. Por causa, do compartilhamento, os ponteiros ficaram acesso a uma memória removida sem a verificação de uso por outras instâncias. Isto também aponta para uso de classe controle o pool de flyweights. 29-abr-09 Leandro Tonietto 145
Exercício/Discussão: Structural Patterns - Flyweight Considere um jogo RTS. Como poderíamos fazer uso de flyweights para economia de memória? Considere um aplicativo multiusuário que aplica filtros imagem sobre fotografias. Por exemplo, vários usuários podem realizar a aplicação dos mesmos filtros enquanto utilizam o sistema. É possível encaixar o padrão flyweight? Mais exemplos do uso de flyweight: Simulação de multidões de objetos. Há muita informação que pode ser compartilhada! 29-abr-09 Leandro Tonietto 146
Exemplo prático 1 (ver código-fonte): aplicação com janelas gráficas utiliza mesmo ícone para cada janela interna que ser aberta na aplicação (Exemplo editor de imagens e "internalframes" que abertos na aplicação). Uma solução é criar um objeto que seja uma fábrica de ícones. Porém quando um ícone já criado é solicitado, a fábrica não precisa instanciar outro apenas retorna o criado anteriormente. Exemplo prático 2 (ver código-fonte): Um sistema com recursos de BD faz uso das mesmas litas auxiliares para diversos cadastros, como por exemplo: listas de uf, países e municípios. Ao invés de executar a consulta todas as vezes em que fosse necessário e remontar uma lista de UFs, o sistema poderia manter um objeto na memória e compartilha-lo com os diversos cadastros do sistema. Exemplo prático 3: Um sistema que gerencia pontos de localidades reconhecidas em um mapa. Os objetos que representam os pontos de interesse e, principalmente, as rotas que levam aos caminhos possíveis entre dois pontos (origem e destino). Podem ser compartilhadas pelos diversos objetos que podem fazer uso delas. 29-abr-09 Leandro Tonietto 147