Para um bom resultado do uso deste padrão,use-o quando todas as afirmativas seguintes forem verdadeiras:
- A aplicação usa um grande número de objetos;
- Custos de armazenamento são grandes por causa da grande quantidade de objetos;
- A maior parte do estado dos objetos podem ser extrínseco (informações que dependem e variam com o contexto do flyweight, e que por esse motivo nao podem ser compartilhados);
- Muitos grupos de objetos podem ser substituídos por poucos objetos que possam ser compartilhados (estado extrínseco deve ser removido para outro lugar);
- A aplicação não depende da identidade do objeto;
Ainda deve-se pensar sobre o ponto fraco do padrão, que é dependendo da quantidade e da organização dos objetos a serem compartilhados, pode haver um grande custo para procura deles. Então ao utilizar o padrão deve ser analisado qual a prioridade no projeto, espaço ou tempo de execução.
Os participantes deste padrão seriam:
- Cliente : computa ou armazena o estado extrínseco do flyweight, assim como mantém a referência para ele;
- Flyweight: declara uma interface por onde pode receber e atuar sobre estados extrínsecos;
- FlyweightFactory: cria e gerencia objetos flyweights e garante que eles sejam compartilhados corretamente. Quando um cliente solicita um flyweight, um objeto FlyweightFactory fornece a ele, ou cria se caso ele não exista.
- ConcretesFlyweights (no exemplo do processador de texto seria o caractere em si): implementa a interface Flyweight e armazena só os estados intrísecos (compartilháveis).
Um bom exemplo da utilização é no desenvolvimento de jogos, afinal são usadas várias imagens que representam as entidades que compõe o jogo (cenário, jogador, inimigo..).
Isso causa duplicação de informação.Por exemplo, quando aparecem vários inimigos iguais no jogo, o mesmo conjunto de imagens é criado repeditas vezes.
Para exemplificar isso em código, começamos criando uma classe Imagem (informação intríseco):
public class Imagem {
protected String NomedaImagem;
public Imagem(String imagem) {
NomedaImagem = imagem;
}
public void desenharImagem() {
System.out.println(NomedaImagem + " desenhada!");
}
}
Entao criar a classe Ponto (informação extrínseco):
public class Ponto {
public int x, y;
public Ponto(int x, int y) {
this.x = x;
this.y = y;
}
}
Uma classe Flyweight será feita para armazenar o método de desenho da imagem em um determinado ponto: public abstract class SpriteFlyweight {
public abstract void desenharImagem(Ponto ponto);
}
Após a criação da classe Flyweight, criamos uma classe Flyweight Concreta, que seria a implementação da operação de fato: public class Sprite extends SpriteFlyweight {
protected Imagem imagem;
public Sprite(String nomeDaImagem) {
imagem = new Imagem(nomeDaImagem);
}
@Override
public void desenharImagem(Ponto ponto) {
imagem.desenharImagem();
System.out.println("No ponto (" + ponto.x + "," + ponto.y + ")!");
}
}
A classe fábrica guardará todas as imagens que serão compartilhadas e terá um método para pega-las, tendo assim todo acesso as imagens centralizado nessa classe: public class FlyweightFactory {
protected ArrayList flyweights;
public enum Sprites {
JOGADOR, INIMIGO_1, INIMIGO_2, CENARIO_1
}
public FlyweightFactory() {
flyweights = new ArrayList();
flyweights.add(new Sprite("jogador.png"));
flyweights.add(new Sprite("inimigo1.png"));
flyweights.add(new Sprite("inimigo2.png"));
flyweights.add(new Sprite("cenario1.png"));
}
public SpriteFlyweight getFlyweight(Sprites jogador) {
switch (jogador) {
case JOGADOR:
return flyweights.get(0);
case INIMIGO_1:
return flyweights.get(1);
case INIMIGO_2:
return flyweights.get(2);
default:
return flyweights.get(3);
}
}
}
E utilizando esse padrão:
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
factory.getFlyweight(Sprites.JOGADOR).desenharImagem(new Ponto(10, 10));
factory.getFlyweight(Sprites.INIMIGO_1).desenharImagem(
new Ponto(100, 10));
factory.getFlyweight(Sprites.INIMIGO_1).desenharImagem(
new Ponto(120, 10));
factory.getFlyweight(Sprites.INIMIGO_1).desenharImagem(
new Ponto(140, 10));
factory.getFlyweight(Sprites.INIMIGO_2).desenharImagem(
new Ponto(60, 10));
factory.getFlyweight(Sprites.INIMIGO_2).desenharImagem(
new Ponto(50, 10));
}
Pode ser implementado algo para eliminar um objeto nao usado mais, liberando ele da memória e diminuindo espaço.Referências :
Livro - Padroes de Projetos - Solucoes Reutilizaveis - Gamma Erich
Site - http://brizeno.wordpress.com/category/padroes-de-projeto/flyweight/
Nenhum comentário:
Postar um comentário