[Resolvido] - Dúvidas no Observer da Apostila Caelum
4 respostas
jamesfrj
Oi pessoal! Cá estou eu apanhando de novo do Ruby, mas não desisto hehe
Estava tentando resolver o desafio 5.13 mas estou tendo dificuldade em entender o Observer no Ruby.
moduleObserverdefinitialize@observers=[]enddefadiciona_observer(observer)@observer<<observerendendclassRestauranteincludeObserverdefqualifica(nota)puts"Restaurante recebeu nota #{nota}"notificaenddefnotifica@observers.eachdo|observer|endendendclassFranquiadefalertaputs"Um restaurante foi qualificado"endendrestaurante=Restaurante.newrestaurante.qualifica(10)
Esse enunciado é apenas a ideia geral do que o desafio está propondo. Nesse caso
específico (do padrão Observer) há suporte da própria linguagem e da biblioteca
padrão para resolver a questão, para isso será preciso fazer o require do arquivo observer:
require"observer"
A ideia do padrão observer é permitir que uma instância de qualquer tipo seja "notificada"
de mudanças ocorridas em outros objetos. O objeto que quer ficar sabendo do que acontece
no mundo lá fora é o observador (observer).
Objetos "observáveis" (observable) permitem que observers se cadastrem como interessados
nas alterações, dessa forma é o observável quem decide como e quando um observer deve ser
notificado.
Abaixo vou mandar um exemplo bem abstrato. Caso fique com alguma dúvida, só dizer
require"observer"classObservavelincludeObservabledefum_metodo_qualquerputs"-> faz qualquer coisa"enddefmudanca_de_estadoputs"> aqui pode acontecer qualquer coisa que..."puts"> altere o estado desse objeto"# invocação do método changed incluído pelo# módulo Observable, marca o objeto atual como# alteradochanged## internamente, o objeto pode decidir quando chamar# o método que irá notificar os observers cadastrados# poderia haver aqui uma lógica para só invocar o método# a seguir (também do módulo Observable) quando o# estado atual do objeto é algum específiconotify_observers(self)# avisando todos os observers que algo aconteceuendendclassCuriosodefupdate(instancia_de_observavel)puts"-> OPA! O objeto #{instancia_de_observavel} foi alterado!"# como a instância do objeto que sofreu alteração foi passada# como parâmetro para notify_observers, temos a referência# para esse objeto disponível por aqui# podemos invocar qualquer um de seus métodosinstancia_de_observavel.um_metodo_qualquerendendum_observavel=Observavel.newum_curioso=Curioso.new# cadastrando um curioso que quer saber da vida de um observavelum_observavel.add_observerum_curioso# invocando um método em observavel que marca o objeto# como alterado, e notifica seus observersum_observavel.mudanca_de_estado# e você ainda pode adicionar outras instâncias de objetos# interessados em observar.# por padrão, um Observable irá invocar o método #update# em um observerclassOutroCuriosodefupdate(observavel)puts"--> sou outro curioso e tambem estou sabendo da mudanca em #{observavel}"endendoutro=OutroCurioso.newum_observavel.add_observeroutroum_observavel.mudanca_de_estado# dois observers são notificados agora
jamesfrj
Olá ricardo.valeriano! Obrigado pela resposta, desculpe ter demorado para dar um feedback. Fiquei envolvido com coisas de trabalho, enfim…
Consegui entender melhor o Observer. Fiz um exemplo aqui com ajuda do seu código.
require"observer"classRestauranteObservavelincludeObservableattr_accessor:nota#Restaurante,oobjetoobservado#MétodoqualificaalteraoestadodoRestauranteenotificaasfranquiasdefqualifica(nota)puts"Restaurante recebeu nota #{nota} <Restaurante>"@nota=nota#notificandoqueoobserverfoialteradochanged#notificaosobservadoresnotify_observers(self)enddefinforma_notaputs"A nota do Restaurante no momento é #{@nota}"puts""endendclassFranquiaPrimeiradefupdate(instancia_de_restaurante_observavel)puts"Sou a franquia um de #{instancia_de_restaurante_observavel} soube que ele foi alterado! <Franquia 1>"instancia_de_restaurante_observavel.informa_notaendendum_restaurante=RestauranteObservavel.newputsfranquia_um=FranquiaPrimeira.new#cadastrandonovaFranquiaum_restaurante.add_observerfranquia_um#MétodoqualificaalteraoestadodoRestauranteenotificaasfranquiasum_restaurante.qualifica(9)classFranquiaDoisdefupdate(observavel)puts"Sou outra franquia sei da mudanca em #{observavel} <Franquia 2>"endendfranquia_dois=FranquiaDois.newum_restaurante.add_observerfranquia_doisum_restaurante.qualifica(7.5)#doisobserverssaonotificadosagora