[Resolvido] - Dúvidas no Observer da Apostila Caelum

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.


module Observer
  def initialize
    @observers = []
  end

  def adiciona_observer(observer)
    @observer << observer
  end
end

class Restaurante
    include Observer

  def qualifica(nota)
    puts "Restaurante recebeu nota #{nota}"
      notifica
  end

  def notifica
    @observers.each do |observer|

    end
  end
end

class Franquia
  def alerta
    puts "Um restaurante foi qualificado"
  end
end

restaurante = Restaurante.new
restaurante.qualifica(10)

Como seria a forma correta de implementar isso?

Alguém?

Tudo bem @jamesfrj? Não desanima não!

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:

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

[code]require "observer"
class Observavel
include Observable

def um_metodo_qualquer
puts "-> faz qualquer coisa"
end

def mudanca_de_estado
puts "> 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
# alterado
changed

## 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ífico

notify_observers(self) # avisando todos os observers que algo aconteceu

end
end

class Curioso
def update(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étodos
instancia_de_observavel.um_metodo_qualquer

end
end

um_observavel = Observavel.new
um_curioso = Curioso.new

cadastrando um curioso que quer saber da vida de um observavel

um_observavel.add_observer um_curioso

invocando um método em observavel que marca o objeto

como alterado, e notifica seus observers

um_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 observer

class OutroCurioso
def update(observavel)
puts "–> sou outro curioso e tambem estou sabendo da mudanca em #{observavel}"
end
end

outro = OutroCurioso.new
um_observavel.add_observer outro

um_observavel.mudanca_de_estado # dois observers são notificados agora[/code]

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"
class RestauranteObservavel
  include Observable
  attr_accessor :nota

  # Restaurante, o objeto observado

  # Método qualifica altera o estado do Restaurante e notifica as franquias
  def qualifica(nota)
    puts "Restaurante recebeu nota #{nota} <Restaurante>"
    @nota = nota
    # notificando que o observer foi alterado 
    changed
    # notifica os observadores
    notify_observers(self)
  end

  def informa_nota
    puts "A nota do Restaurante no momento é #{@nota}"
    puts ""
  end
end

class FranquiaPrimeira
  def update(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_nota
  end
end

um_restaurante = RestauranteObservavel.new
puts
franquia_um = FranquiaPrimeira.new

# cadastrando nova Franquia
um_restaurante.add_observer franquia_um

# Método qualifica altera o estado do Restaurante e notifica as franquias
um_restaurante.qualifica(9)


class FranquiaDois
  def update(observavel)
    puts "Sou outra franquia sei da mudanca em #{observavel} <Franquia 2>"
  end
end

franquia_dois = FranquiaDois.new
um_restaurante.add_observer franquia_dois

um_restaurante.qualifica(7.5) # dois observers sao notificados agora 

A saída foi

Restaurante recebeu nota 9 <Restaurante>
Sou a franquia um de #<RestauranteObservavel:0xb747bd34> soube que ele foi alterado! <Franquia 1>
A nota do Restaurante no momento é 9

Restaurante recebeu nota 7.5 <Restaurante>
Sou a franquia um de #<RestauranteObservavel:0xb747bd34> soube que ele foi alterado! <Franquia 1>
A nota do Restaurante no momento é 7.5

Sou outra franquia sei da mudanca em #<RestauranteObservavel:0xb747bd34> <Franquia 2>

Com isso na sua opinião, posso considerar resolvido este desafio?

Boa @jamesfrj, é exatamente isso. =)

Boa sorte nos estudos e, qualquer questão, é só dizer.