Baixe o app para aproveitar ainda mais
Prévia do material em texto
10/04/2010 1 Padrões de Projeto Carga Horária 67hs Padrões de Responsabilidade Prof. Giuseppe Anthony N. Lima giuseppeanl@gmail.com Instituto Federal de Educação Tecnológica da Paraíba CST – Sistemas para Internet 1 Introdução • Padrões de Responsabilidade – Objetos são modelados para possuírem informações e métodos necessários • Colaborações devem se dar sem acoplamento • O mundo OO distribui responsabilidades para objetos individuais: só operam sobre seus próprios dados • Maior dependência entre classes causa baixa coesão • Responsabilidade – De fazer algo (não de ser algo!) 2 Introdução • Coesão – Baixo acoplamento entre classes de um software – Clareza quanto as responsabilidades de uma classe • Através de seus métodos ou serviços • Baixa coesão causa dificuldades no projeto – Entender – Reusar – Manter 3 Introdução • Baixa coesão? – Extrato bancário public String extrato() { //realiza a consulta dos lançamentos/movimentação bancária do cliente //aplica bônus de pontuação referente a movimentação //aplica multa em caso negativo //realiza extrato na conta de investimento do cliente } Você saberia que tudo isso era de responsabilidade desse método sem visualizar a implementação? Se um cliente de extrato() contava com a funcionalidade de aplicar multa em caso negativo ou de atraso? 4 Introdução • Proporcionando melhor coesão... – Atribuindo responsabilidades específicas: //solução com baixa coesão public String extrato() { //realiza a consulta dos lançamentos/movimentação bancária do cliente //aplica bônus de pontuação referente a movimentação //aplica multa em caso negativo //realiza extrato na conta de investimento do cliente } //solução com a quebra de extrato() para proporcionar melhor coesão public String aplicaBônus() { } public String aplicaMulta(int tipoDeMulta) { } public String extratoInvestimentos() { } Maior clareza? Maior flexibilidade? Maior reuso? 5 Singleton • “Garantir uma determinada classe tenha uma única instância e que forneça um ponto de acesso global a ela” 6 10/04/2010 2 Singleton • Motivação – Como garantir que uma determinada classe seja instanciada uma única vez? • Um único Banco de Dados • Um único arquivo de log • Um único Driver 7 Singleton • Motivação – Comportamento incorreto – Uso excessivo de recursos – Resultados inconsistentes • Para tanto – Como controlar o número de instâncias de classes? – Como impedir o acesso aos construtores? – Como armazenar as instâncias? 8 Singleton • Utilizar classes estáticas diretamente – Não há criação de instâncias • Não há instanciação da entidade de interesse • Ex: Math, System, etc. – Conseqüências • Criadas no início da aplicação • Podem não ser usadas – Apenas por um período de tempo – Permanecem na memória desde a “carga” da aplicação 9 Singleton • Singleton – Garantir que uma determinada instância seja alocada apenas quando necessária e desalocada quando não for mais – Ponto de acesso global • Definir um construtor privado • Declarar um objeto como estático controlar a construção via teste de condição 10 Singleton Class Sigleton { private static Singleton instancia; private String nome; private String idade; private Singleton (String nome, String idade) { this.nome = nome; this.idade = idade; } public static Singleton getInstancia(String nome, String idade) { if (instancia == null) { instancia = new Singleton(nome, idade); } instancia; } 11 Singleton • Lazy Instantiation – Instancia somente quando a classe será utilizada • Eager Instatiation – Instancia no momento da declaração da variável instance • Sincronização – Se mais de um cliente numa aplicação multithreading estiver acessando getInstance() ao mesmo tempo? • Mais de um objeto pode ser criado! 12 10/04/2010 3 Singleton • Sincronização (cont) public static synchronized Singleton getInstance() { if (instance == null) { return instance = new Singleton(); } return instance; } 13 Observer • “Definir uma dependência um para muitos entre objetos de maneira que, quando um objeto muda de estado, todos os seus dependentes são notificados e atualizados automaticamente” Observar a eminência de uma crise ou é ela que deve me avisar quando chegar? 14 Observer • Necessidade de monitorar alterações do estado de um objeto – Objetos interessados utilizam informações sobre o estado de um objeto de interesse – Na alteração desse estado algo deverá ser feito 15 Observer • Exemplo: Sensor de Segurança – Uma aplicação de segurança se utiliza de um sensor – O sensor possui um ponto de sensibilidade • Se houver movimentação • Se a intensidade da vibração for maior que o limite – Caso isso ocorra • Disparar alarme • Disparar central de segurança • Enviar mensagem para proprietário 16 • Representação do Esquema Observer Objeto de Interesse Objeto Interessado Objeto Interessado Objeto Interessado 17 Observer public class SensorSeguranca { private Proprietario p = new Proprietario(); private ControleAlarme ca = new ControleAlarme(); private CentralSeguranca cs = new CentralSeguranca; public void movimento() { p.enviarMsg(); ca.disparar(); cs.chamarPolicia(); cs.chamarSeguranca(); } } Forte acoplamento: observe como a classe se vincula a outros objetos somente para esses saberem quando algo ocorreu. Se quiséssemos retirar ou colocar interessados em tempo de execução isso seria possível? :( 18 10/04/2010 4 Observer • Nosso projeto mudou... – Mudança 1 • Nosso SensorSegurança deve possuir agora um interessado chamado CentralPolicia, o que fazer? – Referenciar como atributo de SensorSeguranca CentralPolicia – Mudança 2 • Se quisesse que SensorSeguranca não possuisse como interessado CentralSegurança, o que fazer? – Retirar a referência de SensorSegurança junto a CentralPolicia 19 Observer • Nossa solução não está muito boa? – O objeto de interesse sabe o que os interessados podem fazer • Conhecem sua interface – Se quisermos adicionar/retirar objetos interessados devemos alterar em tempo de compilação • Alterar o código da classe do objeto de interesse • Forte acoplamento do objeto de interesse com interessados – O tratamento da notificação é realizado no objeto de interesse e não no interessado • Se objeto interessado possuir muitos objetos de interesse haveria muito código “misturado” para tratamento de uma notificação 20 Observer • Solução: Aplicação do Padrão Observer – Os objetos interessados passam a se registrar no objeto de interesse – Definimos as operações no objeto de interesse que devem realizar notificação nos objetos de interessados • Em geral operações que mudam o estado do objeto de interesse – Objeto de interesse não deve saber quem são os interessados de fato • Objetos interessados são reconhecidos apenas por sua interface • Para não cair na tentação de implementar o código de tratamento da notificação • Objeto de interesse deve notificar os interessados na ocorrência de alteração de estado 21 • Representação do Padrão Observer Objeto de Interesse = Subject Se registra no objeto de interesse: add(); remove() Notifica os interessados: notify() 22 Observer • Aplicando o padrão ao nosso aplicativo... public class SensorSeguranca implements Observable { private List<Observer> observers = new ArrayList<Observer>(); public void add(Observer observer) { observers.add(observer); } public void remove(Observer observer) { observers.remove(observer); } publicvoid notify() { while (int 0; i < observers.size(); i++) observers.get(i).update(); } } 23 Observer public class Proprietatio implements Observer { public void update() { enviarMsg(); } } public class CentralSeguranca implements Observer { public void update() { chamarPolicia(); chamarSeguranca(); } } public class ControleAlarme implements Observer { public void update() { disparar(); } } 24 10/04/2010 5 Observer • Se quiséssemos coletar informações sobre o objeto de interesse no interessado? – Passamos como parâmetro do método update um tipo Observable • O método update(Observable obs) do interessado pode fazer um cast para acessar a interface e conseqüentemente os dados de um objeto de interesse – Poderíamos criar uma classe de Event • Event possui uma coleção de objetos dispostos em um mapa <chave, objeto> com uma interface que permita a manipulação dos dados do evento • O método de Observer passa a ser update(Event e) 25 Observer • Aplicabilidade – É possível adicionar e remover observers – Observable não faz distinção de observers • A única coisa de o objeto de interesse sabe é que os interessados implementam uma interface • Conseqüências – Minimiza a responsabilidade de um objeto de interesse em relação a atualização de mudanças nos interessados • O objeto de interesse apenas notifica! • O tratamento de uma notificação é de responsabilidade dos interessados – Permite desenvolver projetos em camadas • Ex.: Elementos de interface ou representações gráficas (interessados) de um objeto e o próprio objeto da camada de negócio (objetos de interesse) – Suporte a comunicação broadcast • Todos os objetos interessados são notificados – Atualizações inesperadas • Se o interessado não estiver preparado para tratar mudança de estado corretamente 26 Observer • Observer em Java 27 Mediator • Intenção – Definir um objeto que encapsula a forma como um conjunto de objetos interage • Esse objeto encapsula as regras de interação entre os objetos participantes – Promover acoplamento fraco durante a comunicação • Evitar que objetos se referenciem uns aos outros explicitamente • O formato das interações (regras) podem variar independentemente 28 Mediator • Projeto OO encoraja a distribuição de comportamentos entre vários objetos – No entanto cada objeto possui um papel • Reforçando boas práticas de projeto... – Reduzir granularidade – Favorecer composição – Atribuir responsabilidades Se isso não for observado haverá proliferação de interconexões entre objetos 29 Mediator • Vamos entender melhor... – Possuímos um grupo de objetos que operam colaborativamente – Os comportamentos foram distribuídos entre esses objetos • Promover a reusabilidade – Essa distribuição tende a gerar muitas interconexões entre os objetos • Acoplamento forte • Aumento da glanularidade 30 10/04/2010 6 Mediator • Exemplo – Temos que construir uma interface gráfica com o usuário com os seguintes widgets... Exemplo Fonte... Rótulo Caixa de Seleção BotõesBotões Campo de texto 31 Mediator • Interconectando... – Ao selecionar tipo de fonte o rótulo deve ser atualizado e ainda: • Ao digitar o nome da fonte no campo de texto a lista de seleção deverá atualizar sua seleção • Ao escolher fonte na lista de seleção o campo de texto deverá conter o nome da fonte – Ao selecionar negrito , sublinhado e itálico o rótulo deve ser atualizado 32 Mediator • Interconexões demais? Se quiséssemos aproveitar algum widget teríamos que levar consigo essas relações! 33 Mediator • Solução – Vamos criar um objeto mediador que organiza a colaboração entre essas classes 34 Mediator public interface Mediator { public void entradaCampoTexto(); public void selecionaNegrito(); public void selecionaItalico(); public void selecionaSublinhar(); public void selecionaItemLista(); } public class FontConfiguratorMediator implements Mediator { //referências aos widgets ou seja aos objetos mediados public void entradaCampoTexto() { //procura por item na lista de seleção se existir seleciona e atualiza rótulo //se não existir não faz nada } public void selecionaNegrito() { //atualiza rótulo como negrito } public void selecionaItalico() { //atualiza rótulo como itálico } public void selecionaSublinhar() { //atualiza rótulo como sublinhado } ... 35 Mediator //continuação de FontConfiguratorMediator... public class FontConfiguratorMediator implements Mediator { public void selecionaItemLista() { //atualiza caixa de texto e rótulo } }// mediador concreto termina aqui! public interface Widget { public abstract void changed(); } public class CampoDeTexto extends JTextField implements Widget { private Mediator med; public void changed () { med.entradaCampoTexto(); } } 36 10/04/2010 7 Mediator public class ListaDeSelecao extends JComboBox implements Widget { private Mediator med; public void changed () { med.selecionaItemLista(); } } public class BotaoItalico extends JButton implements Widget { private Mediator med; public void changed () { med.selecionaItalico(); } } public class BotaoNegrito extends implements Widget { private Mediator med; public void changed () { med.selecionaNegrito(); } } 37 Mediator public class BotaoSublinhado extends JButton implements Widget { private Mediator med; public void changed () { med.selecionaSublinhar(); } } 38 Mediator • Um único objeto Mediador é passado para seus colaboradores – Nesse caso a classe mediadora também poderia ser um Singleton! • A comunicação entre objetos parceiros pode ser feita via Observer quando possível 39 Mediator • Conseqüências – Limitação do uso de herança • Se colaboradores estenderem de uma classe abstrata Colleague... • Então se é fundamental para colaborador possuir herança, então Colleague poderá ser uma interface – Desacoplamento entre parceiros • Classes parceiras desconhecem sua dependência em relação as demais – Simplificação do protocolo das classes • Centralização do controle – Abstração da maneira como objetos cooperam • Se a forma de colaboração dos parceiros variar podemos implementar outro mediador para cada formato de colaboração 40 Mediator • Para pensar... – Projetar um chat através das classes Convidado e Sala • A sala centraliza o envio e recebe mensagem e possuirá uma console, entrada de texto e lista de convidados na sala • Quando uma mensagem for enviada à Sala deve ser repassada aos demais membros • A Sala deve ser flexível para que qualquer Convidado entre ou saia quando quiser. • Quando uma mensagem for enviada por um convidado a mesma deve aparecer em uma console e a ordem dos convidados deve mudar na lista – Dá para utilizar Mediator? • Quem media? • Quais os colaboradores? 41 Proxy • Intenção – “Fornecer um substituto ou marcador de localização para que um objeto possa controlar o acesso a um outro” – Proxy e Dicionário... • Substituto, procurador, representante. 42 10/04/2010 8 Proxy • Motivação – Controlar e gerenciar o acesso a determinados objetos • Controle: quem acessa o objeto? • Gerência: como o acesso ao objeto é feito? 43 Proxy • O que um Proxy faz? – Um objeto atua como substituto/representante de um outro objeto que não pode ser acessado diretamente – Alguns motivos para o objeto não poder ser acessado diretamente • Objeto está localizado na memória de outro computador (objeto remoto) • Controle de acesso (proteção do objeto real) 44 Proxy • TiposComuns de Proxy – Proxy Remoto • Controla o acesso a um objeto remoto – Proxy Virtual • Controla o acesso a um objeto cuja criação é muito onerosa – Proxy de Proteção • Controla o acesso a um objeto real de maneira que o mesmo possa ser utilizado com restrições 45 Proxy Remoto • Proxy Remoto – Representante local para um objeto remoto • Recebe métodos do cliente e repassa para o responsável pelo serviço • Transparente para o cliente – Casos • Aplicações Distribuídas Cliente-Servidor • Web Services – Objetos participantes do serviço • Integração entre sistemas distintos 46 Pilha de Objetos no ServidorPilha de Objetos do Cliente Proxy Remoto Cliente Proxy Objeto Real Remoto acesso 47 Proxy Remoto • Características – O objeto remoto real deve ser acessado de maneira transparente pelo cliente • O cliente desconhece a implementação do acesso – Um objeto real (remoto) e seu proxy representante (no cliente) devem possuir uma interface comum • Define os métodos que um cliente pode chamar remotamente • É a única coisa que o cliente sabe sobre o objeto real remoto! 48 10/04/2010 9 Proxy Remoto • Representação arquitetural Contém os métodos que poderão ser acessados remotamente Cliente não tem conhecimento se é o objeto real ou seu substituto que está sendo utilizado: conhece apenas a interface 49 Proxy Remoto • Java RMI (Remote Method Invocation) – Tecnologia baseada em sistemas distribuídos – Permite a comunicação entre objetos que estão localizados em JVMs diferentes – Semelhante às RPCs (Remote Procedure Call) em C – Disponível no pacote java.rmi.* – Serviços • Serviços de busca (Lookup Service) – Chamada através da localização de um objeto remoto • Registro de serviços (Registry) – Registro de um objeto remoto a partir da aplicação servidora 50 Proxy Remoto • Estudo de caso – Aplicação que implementa um cadastro de clientes de uma loja qualquer (rede utilizando RMI) • Lado cliente: interface gráfica • Lado servidor: modelo e lógica de negócios para cadastrar, remover e buscar clientes 51 Proxy Remoto • Representação da solução com Proxy Nosso objeto real atuará como um servidor, neste caso de cadastro: a partir dele poderemos acessar outros objetos do domínio Será o substituto do nosso Subscriber real no cliente gerado automaticamente quando o objeto é chamado via RMI. Contém código I/O e de rede 52 Proxy Remoto //interface remota public interface RemoteSubscriber extends Remote { public add(Client client) throws RemoteException {}; public remove(Client client) throws RemoteException {}; public search(Client client) throws RemoteException {}; } //criação de uma implementação remota: este é o objeto real public class Subscriber extends UnicastRemoteObject implements RemoteSubscriber { List<Client> clients = new ArrayList<Client>(); public Subscriber() throws RemoteException {}; public add(Client client) throws RemoteException { clients.add (client) }; public remove(Client client) throws RemoteException { clients.remove(client); }; public remove(Client client) throws RemoteException { clients.search(client); }; } 53 Proxy Remoto //essa trecho da classe no servidor que disponibiliza o nosso objeto servidor remoto //no registro RMI public class AplicaçãoServidora { public static void main(String args[]) { Subscriber s = new Subscriber(); Naming.rebind(“//127.0.0.1/RemoteSubscriber”, s); } } Registra o nosso objeto remoto servidor aqui! Agora aplicações em outras máquinas podem chamá-lo! 54 10/04/2010 10 Proxy Remoto //essa classe é o cliente do nosso objeto remoto (executada em outra máquina) public class TesteClienteRemoto { public static void main(String args[]) { RemoteSubscriber rs = (RemoteSubscriber) Naming.lookup(“rmi://127.0.0.1/RemoteSubscriber”); Cliente cli = rs.buscarCliente(“Roberto”); System.out.println(c.getInfo()); } } Cliente por não ser um tipo nativo deve implementar interface Remote e estender Serializable para poder ser utilizado via RMI. Nossa aplicação conhece somente sua interface Busca pelo objeto através da localização e nome de registro fornecido 55 Proxy Remoto O que RMI faz... Cria um que Stub realiza a chamada e implementa o código I/O e de rede Cria um Skeleton que recebe as chamadas e manipula o objeto real 56 Proxy Virtual • Proxy Virtual – Substitui um objeto real cuja criação pode ser demasiado onerosa • Tráfego, largura e banda de rede • Capacidade de processamento • Memória disponível – Exemplo • Uma aplicação de uma loja que carrega uma imagem de um produto no estoque • Essa imagem é um objeto remoto • Enquanto o objeto com a imagem não é carregado exibir uma mensagem Carregando... 57 Proxy Virtual Pilha de Objetos da Aplicação Cliente ImageProxy ImageIcon paintIcon() paintIcon() possui um código que verifica se a imagem está disponível... Outra máquina... Criação do ImageIcon é onerosa pois sua imagem é carregada via rede! 58 Proxy Virtual • Criação de objetos sob demanda • Adiar o curso integral de criação e inicialização do objeto até o momento em que for necessário utilizá-lo – Carregamento de páginas de um documento muito grande » Somente as páginas visualizadas são carregadas do disco rígido para a memória RAM » Uso racional de memória ____ ____ ____ ____ ____ ____ __ ____ ____ ____ ____ ____ ____ _ 59 Proxy Virtual Possui uma referência para ImageIcon: encapsula a criação de ImageIcon a partir do carregamento de uma imagem. Enquanto a imagem não for carregada exibe mensagem “Carregando...” Depois que for possível criar o ImageIcon com a imagem carregada, o ImageProxy se utiliza dos métodos de ImageIcon 60 10/04/2010 11 Proxy • Conseqüências – Introduz um nível de referência indireta • Permite que o objeto resida em um outro servidor , em um espaço de endereçamento diferente (proxy remoto) • Permite que o objeto seja carregado da base somente quando necessário, sob demanda (proxy virtual) 61 Proxy • Diferenças?... – O que há de diferente do proxy ser remoto, virtual ou de proteção é o seu propósito porém... – Todos eles interceptam a chamada de um método pelo cliente, tal interceptação pode: – Disparar requisições em um objeto remoto (proxy atuando como procurador do objeto real) – Fornecer um substituto enquanto o objeto real é criado (proxy atuando como substituto) – Proteger o objeto de interesse (proxy atuando como protetor) 62 Chain of Responsibility • Intenção – Evitar o acoplamento entre objetos solicitantes e atendentes permitindo que mais de um objeto tenha a oportunidade de tratar a solicitação. – Repassar a solicitação para uma cadeia de objetos atendentes até que algum deles seja capaz de tratá-la. Encadeamento de responsabilidades para o tratamento de solicitações! 63 Chain of Responsibility • Representação arquitetural Tratador ou Processador possui sempre uma referência para ele mesmo: forma o sentido da cadeia de tratamento! O método que delega a responsabilidade para um membro da cadeia 64 Chain of Responsibility • Exemplo – Um programa que realiza a conversão de um valor numérico para extenso – Estratégia • Dividir o valor entre a casas decimais • Pegar o resto e encaminhar para o próximo da cadeia Milhar (1000 até 999.999 Centena (100 até 999) Unidade (1 até 9) Dezena (10 até 99) Trata divisão por 1000 e delega resto Trata divisão por 100 e delega resto Trata divisão por 10 edelega resto 65 Chain of Responsibility • Aplicação do padrão no exemplo... Referência para sucessor deve respeitar a ordem da cadeia: de milhar para centena, de centena dezena e de dezena para unidade 66 10/04/2010 12 Chain of Responsibility • Código public abstract class Conversor { protected Processador sucessor; public abstract String converterValorParaExtenso(); public void setSucessor(Processador sucessor) { this.sucessor = sucessor; } } public class ConversorDezena extends Conversor { public ConversorDezena() { sucessor = new ConversorUnidade(); this.sucessor = sucessor; } } 67 Chain of Responsibility //continuação da classe ConversorDezena public String converterValorParaExtenso(int valor) { String aux = “”; int resto = (valor % 10); int quociente = (valor / 10); if ((valor >= 10) && (valor <=19)) { switch (valor) { case 10: aux = “dez”; break; case 11: aux = “onze”;break; ... case 19: aux = “dezenove”; } } } 68 Chain of Responsibility //continuação do método converterValorParaExtenso da classe ConversorDezena if (valor >= 20) { switch(quociente) { case 2: aux = “vinte”; break; case 3: aux = “trinta”; break; case 9: aux = “noventa”; } } if (valor < 10) return sucessor.converterValorParaExtenso(valor); else { if ((valor >= 20) && (resto != 0)) return aux + “ e ” + sucessor.converterValorParaExtenso(resto); return aux; } } 69 Chain of Responsibility //ConversorUnidade (sucessor de ConversorDezena) public class ConversorUnidade extends Conversor { public String converte (int valor) { switch(valor) { case 1: return “um”; case 2: return “dois”; case 3: return “três”; ... case 9: return “nove”; } } } 70 Chain of Responsibility public class ClienteTeste { public static void main(String args[]) { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); Conversor conversor = new ConversorDezena(); String s = null; int valor = 0 ; System.out.println(“Informe um valor”); try { s = br.readLine(); valor = Integer.parseInt(s); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } System.out.println(“O valor ”+valor+” por extenso” +conversor.converterValorParaExtenso(valor)); } } Baixo acoplamento: cliente desconhece os responsáveis ou a composição da cadeia de composições. 71 Chain of Responsibility • Conseqüências – Evita que um objeto (client) seja forçado a tomar conhecimento do outros (handlers) – O objeto só precisa saber que o pedido foi tratado apropriadamente – A estrutura da cadeia não precisa ser conhecida • Recursividade Horizontal – Flexibilidade na atribuição de responsabilidades para objetos (subclasses, alteração dinâmica da cadeia) – Sucesso no tratamento do pedido não é garantido 72 10/04/2010 13 Flyweight • Intenção – Usar compartilhamento para suportar eficientemente grandes quantidades de objetos de glanularidade fina 73 Flyweight • Alta glanularidade: uma aplicação pode demandar o uso de centenas ou milhares de pequenos objetos ao mesmo tempo – Como reduzir o número de objetos – Será que esses objetos possuem características comuns? 74 Flyweight • Explorando os estados de objetos (características) – Estados instrísecos: imutável, estado compartilhado – Estados extrínsecos: mutável, estado não compartilhado 75 Flyweight • Aplicação – Separar a parte mutável da imutável – Criar uma flyweight factory que instancie flyweights e faça com que os clientes as compartilhem – Garantir que os clientes usarão a factory em vez de construírem eles mesmos as instâncias da classe Flyweight. • Singleton de pool de objetos 76 Flyweight • Arquitetura do padrão 77 Flyweight • Um editor de texto que possui uma letra e sua representação (estilo) – Estado instríseco: letra • É imutável, o símbolo de uma letra pode ser compartilhada pois não muda – Estado extrínseco: estilo • É mutável, a representação de uma letra (fonte, cor, tamanho) pode ser alterada. 78 10/04/2010 14 Flyweight public interface Flyweight { public void exibe (String f, int tam, String cor); } public class Letra implements Flyweight { private char simbolo; public Letra(char simbolo) { this.simbolo = simbolo; } public char getSimbolo() { return simbolo; } public void exibe (String f, int tam, String cor) {}; } 79 Flyweight public class Estilo implements Flyweight { private String fonte; private int tam; private String cor; private Letra letra; public Estilo(String fonte, int tam, String cor, Letra letra) { this.fonte = fonte; this.cor = cor; this.tam = tam; this.letra = letra; } //getters & setters ... public void exibe (String f, int tam, String cor) {}; } 80 Flyweight public class LetraFactory { Letra[] alfabeto = new Letra[26]; static int quant = 0; Letra letra; public Letra get(char c) { Letra l; for (int i =0; i< quant; i++) { if (alfabeto[i] != null) if (alfabeto[i].getSimbolo() == c) return alfabeto[i]; } letra = new Letra(c); alfabeto[quant++] = letra; return letra; } 81 Flyweight public class Main { public static void main(String args[]) { LetraFactory lf = new LetraFactory(); Flyweight[] texto = new Estilo(); texto[0] = new Estilo(“ARIAL”, 12, “preto”, lf.get(‘h’)); texto[1] = new Estilo(“ARIAL”, 12, “preto”, lf.get(‘e’)); texto[2] = new Estilo(“ARIAL”, 12, “preto”, lf.get(‘l’)); texto[3] = new Estilo(“ARIAL”, 12, “preto”, lf.get(‘l’)); texto[4] = new Estilo(“COURIER”, 12, “preto”, lf.get(‘o’)); } 82 Flyweight • Conseqüências – Compartilhamento de objetos a fim de reduzir memória alocada – Controle da criação de objetos com estados distintos – Centraliza a responsabilidade em objetos compartilhados de glanularidade fina 83
Compartilhar