Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.
left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Prévia do material em texto

.NET – O padrão de projeto 
Observer
PorJosé Carlos Macoratti em 06/06/2013
3091VIEWS
COMPARTILHE!
O padrão de projeto (Design Pattern) Observer é um padrão comportamental 
que representa uma relação de 1-N (de um para muitos) entre objetos. Assim, 
quando um objeto altera o seu estado, os objetos dependentes serão 
notificados/informados/avisados e atualizados de forma automática. O padrão 
possibilita que objetos sejam avisados da mudança de estado de outros 
eventos ocorrendo em outro objeto.
Podemos dizer de forma simples que o objetivo principal do padrão Observer é 
manter a consistência entre objetos relacionados sem criar um código 
fortemente acoplado.
As expressões “acoplamento fraco” ou “acoplamento forte” são comuns em 
quase todas as discussões sobre projeto de software. O acoplamento entre 
classes ou subsistemas é uma medida da interconexão entre essas classes ou 
subsistemas. O acoplamento forte significa que as classes relacionadas 
precisam conhecer detalhes internos umas das outras, as alterações se 
propagam pelo sistema, e o sistema é potencialmente mais difícil de entender e 
manter.
Acoplamento é o nível de dependência/conhecimento que pode existir entre as 
classes;
•
Uma classe com acoplamento fraco não é dependente de muitas classes para 
fazer o que ele tem que fazer;
•
Uma classe com acoplamento forte depende de muitas outras classes para 
fazer o seu serviço;
•
Uma classe com acoplamento forte é mais difícil de manter, de entender e de 
ser reusada;
•
Em uma definição mais formal, um padrão Observer permite:
“Definir uma dependência um-para-muitos entre objetos para que 
quando um objeto mudar de estado, todos os seus dependentes 
sejam notificados e atualizados automaticamente.” [GoF]
Nota: Padrões de projeto comportamentais são padrões que tratam das 
interações e divisões de responsabilidades entre as classes ou objetos.
O diagrama de classes para o padrão Observer é mostrado na figura abaixo:
sexta-feira, 4 de maio de 2018 03:01
 Página 1 de Padrao Observer 
Classes/Objetos participantes do padrão:
Sujeito (subject): Conhece os seus observadores. Um número qualquer de 
observadores é permitido. Provê uma interface para adicionar/remover 
observadores;
1.
Observador (observer): Define uma interface de atualização para os objetos 
que devem ser notificados sobre as mudanças no sujeito;
2.
Sujeito concreto (ConcreteSubject): Armazena o estado de interesse para os 
objetos de ConcreteObserver; envia uma notificação aos observadores 
concretos quando seu estado mudar;
3.
Observador concreto (ConcreteObserver): Implementa a interface definida 
pelo Observador para tratar as notificações.
4.
O mesmo diagrama de classes traduzido:
Vantagens em usar o padrão 
 Página 2 de Padrao Observer 
Vantagens em usar o padrão 
Observer
Permite um acoplamento mínimo entre o Sujeito(Subjet) e o 
Observador(Observer)
•
Pode reutilizar Sujeitos sem reutilizar os seus observadores e vice-versa;•
Os Observadores podem ser adicionados sem modificar o Sujeito;•
Todo sujeito conhece a sua lista de Observadores;•
O Sujeito não precisa conhecer a classe concreta de um observador, apenas 
que cada observador implementa a interface update();
•
O Sujeito e o Observador podem pertencer a diferentes camadas de abstração.•
Quando usar o padrão Observer?
Quando uma modificação do estado de um objeto implica modificações em 
outros objetos;
•
Quando um objeto deve ser capaz de notificar outros objetos, mas sem 
pressupostos sobre os objetos a serem notificados;
•
Quando uma abstração possuir dois aspectos e um depende do outro;•
Quando não desejamos um forte acoplamento com os objetos que necessitam 
conhecer estas modificações;
•
Questões de Implementação do 
padrão Observer
Como é que o sujeito vai manter o controle de seus observadores?
R: Usando um Array, uma lista ligada etc.
E o que ocorre se um observador quer observar mais de um sujeito?
R: Ele têm que dizer ao observador quem ele é através da interface de 
atualização.
E quem aciona a atualização?
R: O sujeito, sempre que ele muda de estado; os observadores depois de 
causar uma ou mais mudanças de estado; algum outro objeto.
 Página 3 de Padrao Observer 
Obs: Verifique se o Sujeito atualiza o seu estado antes de enviar notificações.
Quanta informação sobre a mudança deve o Sujeito enviar para os 
observadores?
R: No modelo Push – bastante, ou no modelo Pull – muito pouca.
Um observador pode ser um Sujeito?
R: Sim, pode.
Implementando o padrão de projeto 
Observer
Este exemplo foi baseado no livro “Use a Cabeça (head first) Padrões de 
Projeto”, FREEMAN (2007:81-96).
Para implementar o padrão Observer eu vou usar o seguinte cenário:
Imagine que temos Assinantes de um serviço de uma Editora;•
A editora deverá notificar todos os seus assinantes quando houver uma nova 
edição;
•
A nova edição será representada por variável booleana _novaEdicao que 
inicialmente terá o seu valor definido como false;
•
O método alterarEdicao() promove a alteração do estado indicando true 
quando houver uma nova edição;
•
O método getEdicao() obtém o valor atual de _novaEdicao indicando se há 
uma nova edição ou não.
•
Nesse cenário, teremos as seguintes classes:
Sujeito – Interface que define os métodos para Registrar/Remover/Notificar um 
observador;
1.
Observador – Interface que define o método Atualizar() que informa o 
observador quando houver uma alteração do estado do Sujeito;
2.
EditoraConcreta – Classe concreta que implementa interface Sujeito;3.
AssinanteConcreto – Classe concreta que implementa a interface Observador.4.
O Diagrama de classes gerado é visto abaixo:
 Página 4 de Padrao Observer 
Implementando o padrão Observer
Vamos agora criar as classes e verificar o seu funcionamento.
Eu vou usar o Visual Studio 2012 Express Edition e criar uma aplicação 
Console chamada PadraoProjetoObserver.
Obs: Estou disponibilizando também o código para VB .NET criado no Visual 
Studio 2012 Express Edition
No menu Project, clique em Add Class e informe o nome Sujeito.cs/Sujeito.vb e 
a seguir digite o código da classe Sujeito conforme abaixo:
C#
1 namespace PadraoProjetoObserver
2 {
 Página 5 de Padrao Observer 
2 {
3 interface Sujeito
4 {
5 void RegistrarObservador(Observador o);
6 void RemoverObservador(Observador o);
7 void NotificarObservadores();
8 }
9 }
A interface Sujeito de declara os métodos para registrar/remover e notificar 
um observador
C#
1 namespace PadraoProjetoObserver
2 {
3 interface Observador
4 {
5 void Atualizar(Sujeito sujeito);
6 }
7 }
A interface Observador declara o método Atualizar
C#
1 using System;
2 using System.Collections.Generic;
3
4 namespace PadraoProjetoObserver
5 {
6 class EditoraConcreta : Sujeito
7 {
8 private List<Observador> observadores = new List<Observador>();
9 private bool _novaEdicao = false;
10
 Página 6 de Padrao Observer 
11 public void RegistrarObservador(Observador o)
12 {
13 observadores.Add(o);
14 }
15
16 public void RemoverObservador(Observador o)
17 {
18 observadores.Remove(o);
19 }
20
21 public void NotificarObservadores()
22 {
23 foreach (Observador o in observadores)
24 {
25 o.Atualizar(this);
26 }
27 }
28
29 public void alterarEdicao()
30 {
31 if (_novaEdicao)
32 _novaEdicao = false;
33 else
34_novaEdicao = true;
35 NotificarObservadores();
36 }
37
38 public Boolean getEdicao()
39 {
40 return _novaEdicao;
41 }
42 }
43 }
Note que na classe concreta EditoraConcreta estamos chamando o 
método NotificarObservadores() após ocorrer uma mudança de estado no 
objeto EditoraConcreta;
Na implementação do método notificarObservadores, percorremos os 
observadores informando cada instância dele mesmo e informando que o 
 Página 7 de Padrao Observer 
observadores informando cada instância dele mesmo e informando que o 
objeto que estava sendo observado mudou seu estado.
C#
1 using System;
2
3 namespace PadraoProjetoObserver
4 {
5 class AssinanteConcreto : Observador
6 {
7 private EditoraConcreta objetoObservado;
8
9 public AssinanteConcreto(EditoraConcreta o)
10 {
11 objetoObservado = o;
12 objetoObservado.RegistrarObservador(this);
13 }
14
15 public void Atualizar(Sujeito sujeito)
16 {
17 if (sujeito == objetoObservado)
18 {
19 Console.WriteLine("[Aviso] - A editora alterou o seu 
estado para : " + objetoObservado.getEdicao());
20 }
21 }
22 }
23 }
No construtor da classe AssinanteConcreto, criamos o observador e já 
definimos como parâmetro o objeto observado, logo a seguir podemos chamar 
o método adicionarObservador que passa por referência a sua própria 
instância.
Quando o método atualizar é chamado, nós precisamos verificar se a editora 
que alterou o estado é a mesma que estamos observando.
C#
 Página 8 de Padrao Observer 
C#
1 using System;
2
3 namespace PadraoProjetoObserver
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 EditoraConcreta editora = new EditoraConcreta();
10 // Editora ja inicia com valor padrão igual a false
11 AssinanteConcreto assinante1 = new
AssinanteConcreto(editora);
12 AssinanteConcreto assinante2 = new
AssinanteConcreto(editora);
13 AssinanteConcreto assinante3 = new
AssinanteConcreto(editora);
14 AssinanteConcreto assinante4 = new
AssinanteConcreto(editora);
15 AssinanteConcreto assinante5 = new
AssinanteConcreto(editora);
16
17 // Já passando a editora como parametro
18 editora.alterarEdicao();
19 // Nesse momento é chamado o método atualizar
20 // das instâncias assinante1 e assinante2, resultadao:
21 // [Aviso] A Editora mudou seu estado para: true (5 x) 
22 editora.alterarEdicao();
23 //[Aviso] A Editora mudou seu estado para: false (5 x)
24 // Obs: temos 5 saídas porque temos 5 assinantes
25 Console.ReadKey();
26 }
27 }
28 }
Poderíamos dar nomes aos assinantes usando uma string em 
AssinanteConcreto e passar seu nome para o construtor como segundo 
parâmetro.
 Página 9 de Padrao Observer 
O resultado acima mostra a notificação emitida a todos os assinantes 
registrados após a mudança de estado.
Pegue a solução completa aqui:
PadraoProjetoObserver.zip
PadraoProjetoObserverVB.zip
De <https://imasters.com.br/desenvolvimento/visual-basic/net-o-padrao-de-projeto-observer/?trace=1519021197
&source=single> 
 Página 10 de Padrao Observer 
Padrão de design do observador
30/03/2017•
20 minutos para ler•
O padrão de design do observador permite a um assinante se registrar em um 
provedor e receber notificações dele.Ele é adequado para qualquer cenário que 
requer a notificação por push. O padrão define um provedor (também conhecido 
como assunto ou observável) e zero, um ou mais observadores. Observadores 
registram-se com o provedor e, sempre que uma condição, evento ou alteração de 
estado predefinido ocorrer, o provedor notificará automaticamente todos os 
observadores chamando um dos seus métodos. Nessa chamada de método, o 
provedor também pode fornecer informações sobre o estado atual para 
observadores. No .NET Framework, o padrão de design de observador é aplicado 
ao implementar as interfaces 
genéricas System.IObservable<T> e System.IObserver<T>. O parâmetro de tipo 
genérico representa o tipo que fornece informações de notificação.
Aplicando o padrão
O padrão de design do observador é adequado para notificações por push 
distribuídas, pois oferece suporte para uma separação clara entre dois componentes 
diferentes ou camadas de aplicativo, como uma camada de fonte de dados (lógica 
de negócios) uma camada de interface do usuário (exibição). O padrão pode ser 
implementado sempre que um provedor usa retornos de chamada para fornecer 
informações atuais a seus clientes.
Um provedor ou o assunto, que é o objeto que envia notificações para 
observadores. Um provedor é uma classe ou estrutura que implementa a 
interface IObservable<T>. O provedor deve implementar um único 
método, IObservable<T>.Subscribe, que é chamado pelos observadores que 
desejam receber notificações do provedor.
•
Um observador, que é um objeto que recebe notificações de um provedor. Um 
observador é uma classe ou estrutura que implementa a 
interface IObserver<T>. O observador deve implementar três métodos, que são 
chamados pelo provedor:
•
IObserver<T>.OnNext, que fornece ao observador informações novas ou 
atuais.
•
IObserver<T>.OnError, que informa o observador que ocorreu um erro.•
IObserver<T>.OnCompleted, que indica que o provedor terminou de enviar 
notificações.
•
Um mecanismo que permite que o provedor mantenha controle dos 
observadores. Normalmente, o provedor usa um objeto de contêiner, como um 
objeto System.Collections.Generic.List<T>, para manter as referências às 
implementações de IObserver<T> que assinaram notificações. Usar um 
contêiner de armazenamento para essa finalidade permite que o provedor lidar 
com um número ilimitado de observadores. A ordem na qual os observadores 
recebem notificações não está definida. O provedor está livre para usar 
qualquer método para determinar a ordem.
•
Uma implementação de IDisposable que permite que o provedor remova os 
observadores quando a notificação for concluída. Observadores recebem uma 
referência para a implementação de IDisposable do método Subscribe, 
•
A implementação do padrão exige que você forneça o seguinte:
terça-feira, 24 de abril de 2018 10:03
 Página 11 de Padrao Observer 
referência para a implementação de IDisposable do método Subscribe, 
portanto, eles também podem chamar o método IDisposable.Dispose para 
cancelar a assinatura antes que o provedor tenha terminado de enviar 
notificações.
Um objeto que contém os dados que o provedor envia para seus 
observadores. O tipo desse objeto corresponde ao parâmetro de tipo genérico 
das interfaces IObservable<T> e IObserver<T>. Embora esse objeto possa ser 
o mesmo que a implementação de IObservable<T>, geralmente ele é um tipo 
separado.
•
Observação
Além de implementar o padrão de design do observador, pode ser interessante 
explorar bibliotecas que são criadas usando as 
interfaces IObservable<T> e IObserver<T>. Por exemplo, Extensões Reativas 
para .NET (Rx)consistem em um conjunto de métodos de extensão e operadores de 
sequência padrão LINQ para oferecer suporte à programação assíncrona.
Implementando o padrão
O exemplo a seguir usa o padrão de design do observador para implementar um 
sistema de informações de coleta de bagagem de aeroporto. Uma 
classe BaggageInfo fornece informações sobre voos que chegam e as esteiras 
onde as bagagens de cada voo estão disponíveis pararetirada. Isso é mostrado no 
exemplo a seguir.
C#Copiar
using System;
using System.Collections.Generic;
public class BaggageInfo
{
 private int flightNo;
 private string origin;
 private int location;
internal BaggageInfo(int flight, string from, int carousel)
 {
 this.flightNo = flight;
 this.origin = from;
 this.location = carousel;
 }
public int FlightNumber {
 get { return this.flightNo; }
 }
public string From {
 get { return this.origin; }
 }
public int Carousel {
 get { return this.location; }
 }
}
observers - Uma coleção de clientes que receberão informações atualizadas.•
flights - Uma coleção de voos e suas respectivas esteiras.•
Uma classe BaggageHandler é responsável por receber informações sobre os voos 
que chegam e as esteiras de coleta de bagagem. Internamente, ela mantém duas 
coleções:
Ambas as coleções são representadas por objetos List<T> genéricos que são 
instanciados no construtor de classe BaggageHandler. O código-fonte para a 
classe BaggageHandler é mostrado no exemplo a seguir.
 Página 12 de Padrao Observer 
classe BaggageHandler é mostrado no exemplo a seguir.
C#Copiar
public class BaggageHandler : IObservable<BaggageInfo>
{
 private List<IObserver<BaggageInfo>> observers;
 private List<BaggageInfo> flights;
public BaggageHandler()
 {
 observers = new List<IObserver<BaggageInfo>>();
 flights = new List<BaggageInfo>();
 }
public IDisposable Subscribe(IObserver<BaggageInfo> observer)
 {
 // Check whether observer is already registered. If not, add it
 if (! observers.Contains(observer)) {
 observers.Add(observer);
 // Provide observer with existing data.
 foreach (var item in flights)
 observer.OnNext(item);
 }
 return new Unsubscriber<BaggageInfo>(observers, observer);
 }
// Called to indicate all baggage is now unloaded.
 public void BaggageStatus(int flightNo)
 {
 BaggageStatus(flightNo, String.Empty, 0);
 }
public void BaggageStatus(int flightNo, string from, int carousel)
 {
 var info = new BaggageInfo(flightNo, from, carousel);
// Carousel is assigned, so add new info object to list.
 if (carousel > 0 && ! flights.Contains(info)) {
 flights.Add(info);
 foreach (var observer in observers)
 observer.OnNext(info);
 }
 else if (carousel == 0) {
 // Baggage claim for flight is done
 var flightsToRemove = new List<BaggageInfo>();
 foreach (var flight in flights) {
 if (info.FlightNumber == flight.FlightNumber) {
 flightsToRemove.Add(flight);
 foreach (var observer in observers)
 observer.OnNext(info);
 }
 }
 foreach (var flightToRemove in flightsToRemove)
 flights.Remove(flightToRemove);
flightsToRemove.Clear();
 }
 }
public void LastBaggageClaimed()
 {
 foreach (var observer in observers)
 observer.OnCompleted();
 Página 13 de Padrao Observer 
 observer.OnCompleted();
observers.Clear();
 }
}
Clientes que desejem receber informações atualizadas devem chamar o 
método BaggageHandler.Subscribe. Se o cliente não tiver assinado as 
notificações anteriormente, uma referência para a implementação IObserver<T> do 
cliente será adicionada à coleção observers.
O método BaggageHandler.BaggageStatus sobrecarregado pode ser chamado 
para indicar que bagagem de um voo está sendo descarregada ou que não está 
mais sendo descarregada. No primeiro caso, o método recebe um número de voo, o 
aeroporto que originou o voo e a esteira onde bagagem está sendo 
descarregada. No segundo caso, o método recebe apenas um número de voo. Para 
a bagagem que está sendo descarregada, o método verifica se as informações 
de BaggageInfo passadas para o método existem na coleção flights. Se não 
existirem, o método adicionará as informações e chamará o método OnNext de cada 
observador. Para voos cuja bagagem não está mais sendo descarregada, o método 
verificará se as informações sobre esse voo estão armazenadas na 
coleção flights.Se estiverem, o método chamará o método OnNext de cada 
observador e removerá o objeto BaggageInfo da coleção flights.
Quando o último voo do dia tiver aterrizado e sua bagagem tiver sido processada, o 
método BaggageHandler.LastBaggageClaimed será chamado. Esse método 
chama o método OnCompleted de cada observador para indicar que todas as 
notificações foram finalizadas e, em seguida, limpa a coleção observers.
O método Subscribe do provedor retorna uma implementação de IDisposable que 
permite que os observadores interrompam o recebimento de notificações antes que 
o método OnCompleted seja chamado. O código-fonte para essa 
classe Unsubscriber(Of BaggageInfo) é mostrado no exemplo a seguir. Quando 
a classe é instanciada no método BaggageHandler.Subscribe, ela é passado 
como referência para a coleção observers e uma referência para o observador que 
é adicionado à coleção. Essas referências são atribuídas a variáveis locais. Quando 
o método Dispose do objeto é chamado, ele verifica se o observador ainda existe 
na coleção observers e, em caso afirmativo, remove o observador.
C#Copiar
internal class Unsubscriber<BaggageInfo> : IDisposable
{
 private List<IObserver<BaggageInfo>> _observers;
 private IObserver<BaggageInfo> _observer;
internal Unsubscriber(List<IObserver<BaggageInfo>> observers, 
IObserver<BaggageInfo> observer)
 {
 this._observers = observers;
 this._observer = observer;
 }
public void Dispose() 
 {
 if (_observers.Contains(_observer))
 _observers.Remove(_observer);
 }
}
O exemplo a seguir fornece uma implementação 
de IObserver<T> denominada ArrivalsMonitor, que é uma classe base que exibe 
informações de coleta de bagagem. As informações são exibidas em ordem 
alfabética, pelo nome da cidade de origem. Os métodos de ArrivalsMonitor são 
marcados como overridable (no Visual Basic) ou virtual(em C#), portanto, todos 
podem ser substituídos por uma classe derivada.
 Página 14 de Padrao Observer 
podem ser substituídos por uma classe derivada.
C#Copiar
using System;
using System.Collections.Generic;
public class ArrivalsMonitor : IObserver<BaggageInfo>
{
 private string name;
 private List<string> flightInfos = new List<string>();
 private IDisposable cancellation;
 private string fmt = "{0,-20} {1,5} {2, 3}";
public ArrivalsMonitor(string name)
 {
 if (String.IsNullOrEmpty(name))
 throw new ArgumentNullException("The observer must be assigned a 
name.");
this.name = name;
 }
public virtual void Subscribe(BaggageHandler provider)
 {
 cancellation = provider.Subscribe(this);
 }
public virtual void Unsubscribe()
 {
 cancellation.Dispose();
 flightInfos.Clear();
 }
public virtual void OnCompleted() 
 {
 flightInfos.Clear();
 }
// No implementation needed: Method is not called by the BaggageHandler 
class.
 public virtual void OnError(Exception e)
 {
 // No implementation.
 }
// Update information.
 public virtual void OnNext(BaggageInfo info) 
 {
 bool updated = false;
// Flight has unloaded its baggage; remove from the monitor.
 if (info.Carousel == 0) {
 var flightsToRemove = new List<string>();
 string flightNo = String.Format("{0,5}", info.FlightNumber);
 
 foreach (var flightInfo in flightInfos) {
 if (flightInfo.Substring(21, 5).Equals(flightNo)){
 flightsToRemove.Add(flightInfo);
 updated = true;
 }
 }
 foreach (var flightToRemove in flightsToRemove)
 flightInfos.Remove(flightToRemove);
flightsToRemove.Clear();
 }
 Página 15 de Padrao Observer 
 }
 else {
 // Add flight if it does not exist in the collection.
 string flightInfo = String.Format(fmt, info.From, 
info.FlightNumber, info.Carousel);
 if (! flightInfos.Contains(flightInfo)) {
 flightInfos.Add(flightInfo);
 updated = true;
 }
 }
 if (updated) {
 flightInfos.Sort();
 Console.WriteLine("Arrivals information from {0}", this.name);
 foreach (var flightInfo in flightInfos)
 Console.WriteLine(flightInfo);
Console.WriteLine();
 }
 }
}
A classe ArrivalsMonitor inclui os métodos Subscribe e Unsubscribe. O 
método Subscribe permite que a classe salve a implementação 
de IDisposable retornada pela chamada para Subscribe para uma variável 
particular. O método Unsubscribe permite que a classe cancele a assinatura de 
notificações ao chamar a implementação de Dispose do 
provedor. ArrivalsMonitor também fornece implementações dos 
métodos OnNext, OnError, e OnCompleted. Somente a implementação 
de OnNext contém uma quantidade significativa de código. O método funciona com 
um objeto List<T> particular, classificado e genérico que mantém informações sobre 
os aeroportos de origem dos voos que chegam e sobre as esteiras nas quais as 
respectivas bagagens estarão disponíveis. Se a classe BaggageHandler relata um 
novo voo chegando, a implementação do método OnNext adiciona informações 
sobre esse voo à lista. Se a classe BaggageHandler relata que a bagagem do voo 
foi descarregada, o método OnNextremove essa voo da lista. Sempre que uma 
alteração é feita, a lista é classificada e exibida no console.
O exemplo a seguir contém o ponto de entrada do aplicativo que instancia a 
classe BaggageHandler, bem como duas instâncias da classe ArrivalsMonitor e 
usa o método BaggageHandler.BaggageStatus para adicionar e remover 
informações sobre voos que chegam. Em cada caso, os observadores recebem 
atualizações e exibem corretamente as informações de coleta de bagagem.
C#Copiar
using System;
using System.Collections.Generic;
public class Example
{
 public static void Main()
 {
 BaggageHandler provider = new BaggageHandler();
 ArrivalsMonitor observer1 = new
ArrivalsMonitor("BaggageClaimMonitor1");
 ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit");
provider.BaggageStatus(712, "Detroit", 3);
 observer1.Subscribe(provider);
 provider.BaggageStatus(712, "Kalamazoo", 3);
 provider.BaggageStatus(400, "New York-Kennedy", 1);
 provider.BaggageStatus(712, "Detroit", 3);
 Página 16 de Padrao Observer 
 provider.BaggageStatus(712, "Detroit", 3);
 observer2.Subscribe(provider);
 provider.BaggageStatus(511, "San Francisco", 2);
 provider.BaggageStatus(712);
 observer2.Unsubscribe();
 provider.BaggageStatus(400);
 provider.LastBaggageClaimed();
 }
}
// The example displays the following output:
// Arrivals information from BaggageClaimMonitor1
// Detroit 712 3
//
// Arrivals information from BaggageClaimMonitor1
// Detroit 712 3
// Kalamazoo 712 3
//
// Arrivals information from BaggageClaimMonitor1
// Detroit 712 3
// Kalamazoo 712 3
// New York-Kennedy 400 1
//
// Arrivals information from SecurityExit
// Detroit 712 3
//
// Arrivals information from SecurityExit
// Detroit 712 3
// Kalamazoo 712 3
//
// Arrivals information from SecurityExit
// Detroit 712 3
// Kalamazoo 712 3
// New York-Kennedy 400 1
//
// Arrivals information from BaggageClaimMonitor1
// Detroit 712 3
// Kalamazoo 712 3
// New York-Kennedy 400 1
// San Francisco 511 2
//
// Arrivals information from SecurityExit
// Detroit 712 3
// Kalamazoo 712 3
// New York-Kennedy 400 1
// San Francisco 511 2
//
// Arrivals information from BaggageClaimMonitor1
// New York-Kennedy 400 1
// San Francisco 511 2
//
// Arrivals information from SecurityExit
// New York-Kennedy 400 1
// San Francisco 511 2
//
// Arrivals information from BaggageClaimMonitor1
// San Francisco 511 2
 Página 17 de Padrao Observer 
// San Francisco 511 2
Tópicos relacionados
Título Descrição
Práticas recomendadas para o 
padrão de design do observador
São descritas as práticas recomendadas ao desenvolver 
aplicativos que implementam o padrão de design do 
observador.
Como implementar um provedor É fornecida uma implementação passo a passo de um provedor 
para uma aplicativo de monitoramento de temperatura.
Como implementar um 
observador
É fornecida uma implementação passo a passo de um 
observador para uma aplicativo de monitoramento de 
temperatura.
De <https://docs.microsoft.com/pt-br/dotnet/standard/events/observer-design-pattern> 
 Página 18 de Padrao Observer 
Práticas recomendadas para o padrão de design 
do observador
30/03/2017•
6 minutos para ler•
Colaboradores•
No .NET Framework, o padrão de design de observador é implementado como um 
conjunto de interfaces. A interface System.IObservable<T> representa o provedor 
de dados, que também é responsável por fornecer uma 
implementação IDisposable que permite que os observadores cancelem a 
assinatura de notificações. A interface System.IObserver<T> representa o 
observador. Este tópico descreve as práticas recomendadas que os 
desenvolvedores devem seguir ao implementar o padrão de design de observador 
usando essas interfaces.
Threading
Normalmente, um provedor implementa o 
método IObservable<T>.Subscribe adicionando um observador específico a uma 
lista de assinantes que é representada por algum objeto de coleção e implementa o 
método IDisposable.Dispose removendo um determinado observador da lista de 
assinantes. Um observador pode chamar esses métodos a qualquer momento. Além 
disso, como o contrato de provedor/observador não especifica quem é responsável 
por cancelar a assinatura após o método de retorno de 
chamada IObserver<T>.OnCompleted, o provedor e o observador podem tentar 
ambos remover o mesmo membro da lista. Devido a essa possibilidade, tanto o 
método Subscribe quanto o método Dispose devem ser thread-safe. Normalmente, 
isso envolve o uso de uma coleção simultânea ou um bloqueio. As implementações 
que não são thread-safe devem documentar explicitamente esse fato.
Quaisquer garantias adicionais devem ser especificadas em uma camada no início 
do contrato de provedor/observador. Os implementadores devem chamar 
claramente ao imporem requisitos adicionais para evitar confusão do usuário sobre 
o contrato do observador.
Tratando exceções
Devido ao fraco acoplamento entre um provedor de dados e um observador, as 
exceções no padrão de design do observador devem ser informativas. Isso afeta 
como os provedores e observadores manipulam exceções no padrão de design do 
observador.
O provedor – Chamando o método OnError
O métodoOnError serve como uma mensagem informativa para observadores, da 
mesma forma que o método IObserver<T>.OnNext. No entanto, o 
método OnNext foi projetado para fornecer a um observador dados atuais ou 
terça-feira, 24 de abril de 2018 10:04
 Página 19 de Padrao Observer 
método OnNext foi projetado para fornecer a um observador dados atuais ou 
atualizados, enquanto o método OnError foi projetado para indicar que o provedor 
não é capaz de fornecer dados válidos.
O provedor deverá manipular suas próprias exceções se houver algum 
requisito específico.
•
O provedor não deve esperar ou exigir que os observadores manipulem 
exceções de alguma maneira específica.
•
O provedor deve chamar o método OnError ao manipular uma exceção que 
comprometa sua capacidade de fornecer atualizações. Informações sobre 
essas exceções podem ser passadas para o observador. Em outros casos, não 
há necessidade de notificar os observadores com relação a uma exceção.
•
O provedor deve seguir essas práticas recomendadas ao manipular exceções e 
chamar o método OnError:
Uma vez que o provedor chame o método OnError ou IObserver<T>.OnCompleted, 
não deverá haver nenhuma notificação adicional e o provedor poderá cancelar a 
assinatura de seus observadores. No entanto, os observadores podem também 
cancelar eles próprios sua assinatura a qualquer momento, inclusive antes e depois 
de receberem uma notificação OnError ou IObserver<T>.OnCompleted. O padrão 
de design do observador não determina se o provedor ou o observador é 
responsável pelo cancelamento da assinatura; portanto, é possível que ambos 
tentem cancelar a assinatura. Normalmente, quando os observadores cancelam a 
assinatura, eles são removidos de uma coleção de assinantes. Em um aplicativo de 
thread único, a implementação IDisposable.Dispose deve garantir que uma 
referência de objeto seja válida e que o objeto seja um membro da coleção de 
assinantes antes de tentar removê-lo. Em um aplicativo com multithread, deve-se 
usar um objeto de coleção thread-safe, tal como um 
objeto System.Collections.Concurrent.BlockingCollection<T>.
O observador – Implementando o método OnError
Quando um observador recebe uma notificação de erro de um provedor, o 
observador deve tratar a exceção como informativa e não deve ser necessária 
qualquer ação específica.
O observador não deve lançar exceções de suas implementações de interface, 
tais como OnNext ou OnError.No entanto, se o observador lançar exceções, 
ele deverá esperar que essas exceções fiquem sem tratamento.
•
Para preservar a pilha de chamadas, um observador que deseja gerar um 
objeto Exception, que foi passado para o seu método OnError, deveria 
encapsular a exceção antes de lançá-la. Um objeto de exceção padrão deve 
ser usado para essa finalidade.
•
O observador deve seguir essas práticas recomendadas ao responder a uma 
chamada de método OnError de um provedor:
Práticas recomendadas adicionais
A tentativa de cancelar registro no método IObservable<T>.Subscribe pode resultar 
em uma referência nula.Portanto, é recomendável que você evite essa prática.
Embora seja possível anexar um observador para vários provedores, o padrão 
recomendado é anexar uma IObserver<T> instância a uma única 
instância IObservable<T>.
Consulte também
Padrão de design do observador
Como implementar um observador
 Página 20 de Padrao Observer 
Como implementar um observador
Como implementar um provedor
De <https://docs.microsoft.com/pt-br/dotnet/standard/events/observer-design-pattern-best-practices> 
 Página 21 de Padrao Observer 
Como implementar um provedor
30/03/2017•
9 minutos para ler•
Colaboradores•
O padrão de design do observador requer uma divisão entre um provedor, que 
monitora os dados e envia notificações e um ou mais observadores, que recebem 
notificações (retornos de chamada) do provedor. Este tópico discute como criar um 
provedor. Um tópico relacionado, Como implementar um observador, descreve 
como criar um observador.
Defina os dados que o provedor é responsável por enviar para os 
observadores. Embora o provedor e os dados que ele envia para observadores 
possam ser um tipo único, geralmente são representados por tipos 
diferentes.Por exemplo, em um aplicativo de monitoramento de temperatura, a 
estrutura Temperature define os dados que o provedor (que é representado 
pela classe TemperatureMonitor definida na próxima etapa) monitora e quais 
observadores assinar.
C#Copiar
using System;
public struct Temperature
{
 private decimal temp;
 private DateTime tempDate;
public Temperature(decimal temperature, DateTime dateAndTime)
 {
 this.temp = temperature;
 this.tempDate = dateAndTime;
 }
public decimal Degrees
 { get { return this.temp; } }
public DateTime Date
 { get { return this.tempDate; } }
}
1.
Defina o provedor de dados, que é um tipo que implementa a 
interface System.IObservable<T>. O argumento de tipo genérico do provedor é 
o tipo que o provedor envia a observadores. O exemplo a seguir define uma 
classe TemperatureMonitor, que é uma implementação 
construída System.IObservable<T> com um argumento de tipo genérico 
de Temperature.
C#Copiar
using System;
2.
Para criar um provedor
terça-feira, 24 de abril de 2018 10:04
 Página 22 de Padrao Observer 
using System;
using System.Collections.Generic;
public class TemperatureMonitor : IObservable<Temperature>
{
Determine como o provedor armazena as referências a observadores para que 
cada observador possa ser notificado quando apropriado. Normalmente, um 
objeto de coleção como um objeto genérico List<T> é usado para essa 
finalidade. O exemplo a seguir define um objeto particular List<T> que é 
instanciado no constructo de classe TemperatureMonitor.
C#Copiar
using System;
using System.Collections.Generic;
public class TemperatureMonitor : IObservable<Temperature>
{
 List<IObserver<Temperature>> observers;
public TemperatureMonitor()
 {
 observers = new List<IObserver<Temperature>>();
 }
3.
Defina uma implementação IDisposable que o provedor possa retornar para os 
assinantes para que eles possam interromper o recebimento de notificações a 
qualquer momento. O exemplo a seguir define uma 
classe Unsubscriber aninhada para a qual é passada uma referência à 
coleção de assinantes e ao assinante quando a classe é instanciada. Esse 
código permite que o assinante chame a 
implementação IDisposable.Dispose do objeto para se remover da coleção de 
assinantes.
C#Copiar
private class Unsubscriber : IDisposable
{
 private List<IObserver<Temperature>> _observers;
 private IObserver<Temperature> _observer;
public Unsubscriber(List<IObserver<Temperature>> observers, 
IObserver<Temperature> observer)
 {
 this._observers = observers;
 this._observer = observer;
 }
public void Dispose() 
 {
 if (! (_observer == null)) _observers.Remove(_observer);
 }
}
4.
Implementar o método de IObservable<T>.Subscribe . O método recebe uma 
referência para a interface System.IObserver<T> e deve ser armazenado no 
objeto criado para essa finalidade na etapa 3. O método deve retornar a 
implementação IDisposable desenvolvida na etapa 4. O exemplo a seguir 
mostra a implementação do método Subscribe na 
classe TemperatureMonitor.
C#Copiar
public IDisposable Subscribe(IObserver<Temperature> observer)
5.
 Página 23 de Padrao Observer 
public IDisposable Subscribe(IObserver<Temperature> observer)
{
 if (! observers.Contains(observer))
 observers.Add(observer);
return new Unsubscriber(observers, observer);
}
Notificar os observadores conforme apropriado, chamando as 
implementações IObserver<T>.OnNext, IObserver<T>.OnErrore IObserver<T>
.OnCompleted. Em alguns casos, um provedor não pode chamar o 
método OnError quando ocorre um erro. Por exemplo, o 
método GetTemperature a seguir simula um monitor que lê dados de 
temperatura a cada cinco segundos e notifica os observadores se a 
temperatura foi alterada em pelo menos 0,1 grau desde a leitura anterior. Se o 
dispositivo não relatar uma temperatura (ou seja, se o valor for nulo), o 
provedor notificará observadores de que a transmissão foi concluída. Observe 
que, além de chamar o método OnCompleted de cada observador, o 
método GetTemperature limpa a coleção List<T>.Nesse caso, o provedor não 
torna nenhuma chamada para o método OnError de seus observadores.
C#Copiar
public void GetTemperature()
{
 // Create an array of sample data to mimic a temperature 
device.
 Nullable<Decimal>[] temps = {14.6m, 14.65m, 14.7m, 14.9m, 
14.9m, 15.2m, 15.25m, 15.2m,
 15.4m, 15.45m, null };
 // Store the previous temperature, so notification is only 
sent after at least .1 change.
 Nullable<Decimal> previous = null;
 bool start = true;
foreach (var temp in temps) {
 System.Threading.Thread.Sleep(2500);
 if (temp.HasValue) {
 if (start || (Math.Abs(temp.Value - previous.Value) >= 
0.1m )) {
 Temperature tempData = new Temperature(temp.Value, 
DateTime.Now);
 foreach (var observer in observers)
 observer.OnNext(tempData);
 previous = temp;
 if (start) start = false;
 }
 }
 else {
 foreach (var observer in observers.ToArray())
 if (observer != null) observer.OnCompleted();
observers.Clear();
 break;
 }
 }
}
6.
 Página 24 de Padrao Observer 
Exemplo
O exemplo a seguir contém o código-fonte completo para definir uma 
implementação IObservable<T> para uma aplicativo de monitoramento de 
temperatura. Ele inclui a estrutura Temperature, os dados enviados para 
observadores e a classe TemperatureMonitor, que é a 
implementação IObservable<T>.
C#Copiar
using System.Threading;
using System;
using System.Collections.Generic;
public class TemperatureMonitor : IObservable<Temperature>
{
 List<IObserver<Temperature>> observers;
public TemperatureMonitor()
 {
 observers = new List<IObserver<Temperature>>();
 }
private class Unsubscriber : IDisposable
 {
 private List<IObserver<Temperature>> _observers;
 private IObserver<Temperature> _observer;
public Unsubscriber(List<IObserver<Temperature>> observers, 
IObserver<Temperature> observer)
 {
 this._observers = observers;
 this._observer = observer;
 }
public void Dispose() 
 {
 if (! (_observer == null)) _observers.Remove(_observer);
 }
 }
public IDisposable Subscribe(IObserver<Temperature> observer)
 {
 if (! observers.Contains(observer))
 observers.Add(observer);
return new Unsubscriber(observers, observer);
 }
public void GetTemperature()
 {
 // Create an array of sample data to mimic a temperature device.
 Nullable<Decimal>[] temps = {14.6m, 14.65m, 14.7m, 14.9m, 14.9m, 
15.2m, 15.25m, 15.2m,
 15.4m, 15.45m, null };
 // Store the previous temperature, so notification is only sent 
after at least .1 change.
 Nullable<Decimal> previous = null;
 bool start = true;
foreach (var temp in temps) {
 System.Threading.Thread.Sleep(2500);
 if (temp.HasValue) {
 if (start || (Math.Abs(temp.Value - previous.Value) >= 0.1m )) 
{
 Temperature tempData = new Temperature(temp.Value, 
 Página 25 de Padrao Observer 
 Temperature tempData = new Temperature(temp.Value, 
DateTime.Now);
 foreach (var observer in observers)
 observer.OnNext(tempData);
 previous = temp;
 if (start) start = false;
 }
 }
 else {
 foreach (var observer in observers.ToArray())
 if (observer != null) observer.OnCompleted();
observers.Clear();
 break;
 }
 }
 }
}
Consulte também
IObservable<T>
Padrão de design do observador
Como implementar um observador
Práticas recomendadas para o padrão de design do observador
De <https://docs.microsoft.com/pt-br/dotnet/standard/events/how-to-implement-a-provider> 
 Página 26 de Padrao Observer 
Como implementar um observador
30/03/2017•
5 minutos para ler•
Colaboradores•
O padrão de design do observador exige uma divisão entre um observador, que 
registra as notificações, e um provedor, que monitora os dados e envia notificações 
e um ou mais observadores. Este tópico discute como criar um observador. Um 
tópico relacionado, Como implementar um provedor, descreve como criar um 
provedor.
Defina o observador, que é um tipo que implementa a 
interface System.IObserver<T>. Por exemplo, o código a seguir define um tipo 
chamado TemperatureReporter, que é uma 
implementação System.IObserver<T>construída com um argumento de tipo 
genérico de Temperature.
C#Copiar
public class TemperatureReporter : IObserver<Temperature>
1.
Se o observador puder interromper o recebimento de notificações antes de o 
provedor chamar sua implementação de IObserver<T>.OnCompleted, defina 
uma variável privada que armazenará a implementação 
de IDisposable retornada pelo método IObservable<T>.Subscribe do 
provedor. Você também deve definir um método de assinatura que chama o 
método Subscribe do provedor e armazena o objeto IDisposable retornado.Por 
exemplo, o código a seguir define uma variável privada 
chamada unsubscriber, e define um método Subscribe que chama o 
método Subscribe do provedor e atribui o objeto retornado à 
variável unsubscriber.
C#Copiar
public class TemperatureReporter : IObserver<Temperature>
{
 private IDisposable unsubscriber;
 private bool first = true;
 private Temperature last;
public virtual void Subscribe(IObservable<Temperature> provider)
 {
 unsubscriber = provider.Subscribe(this);
 }
2.
Defina um método que permite ao observador interromper o recebimento de 
notificações antes de o provedor chamar sua implementação 
de IObserver<T>.OnCompleted, se esse recurso for necessário. O exemplo a 
seguir define um método Unsubscribe.
C#Copiar
public virtual void Unsubscribe()
{
3.
Para criar um observador
terça-feira, 24 de abril de 2018 10:06
 Página 27 de Padrao Observer 
{
 unsubscriber.Dispose();
}
Forneça implementações dos três métodos definidos pela 
interface IObserver<T>: IObserver<T>.OnNext, IObserver<T>.OnError e IObser
ver<T>.OnCompleted. Dependendo do provedor e das necessidades do 
aplicativo, os métodos OnError e OnCompleted podem ser implementações de 
stub. Observe que o método OnError não deve tratar do 
objeto Exception transmitido como uma exceção, e o método OnCompleted é 
livre para chamar a implementação IDisposable.Dispose do provedor. O 
exemplo a seguir mostra a implementação IObserver<T> da 
classe TemperatureReporter.
C#Copiar
public virtual void OnCompleted() 
{
 Console.WriteLine("Additional temperature data will not be 
transmitted.");
}
public virtual void OnError(Exception error)
{
 // Do nothing.
}
public virtual void OnNext(Temperature value)
{
 Console.WriteLine("The temperature is {0}°C at {1:g}", 
value.Degrees, value.Date);
 if (first)
 {
 last = value;
 first = false;
 }
 else
 {
 Console.WriteLine(" Change: {0}° in {1:g}", 
value.Degrees - last.Degrees,value.Date.ToUniversalTime() - last.Date.ToUniversalTime());
 }
}
4.
Exemplo
O exemplo a seguir contém o código-fonte completo para a 
classe TemperatureReporter, que fornece a implementação IObserver<T> para 
uma aplicativo de monitoramento de temperatura.
C#Copiar
public class TemperatureReporter : IObserver<Temperature>
{
 private IDisposable unsubscriber;
 private bool first = true;
 private Temperature last;
public virtual void Subscribe(IObservable<Temperature> provider)
 {
 Página 28 de Padrao Observer 
 {
 unsubscriber = provider.Subscribe(this);
 }
public virtual void Unsubscribe()
 {
 unsubscriber.Dispose();
 }
public virtual void OnCompleted() 
 {
 Console.WriteLine("Additional temperature data will not be 
transmitted.");
 }
public virtual void OnError(Exception error)
 {
 // Do nothing.
 }
public virtual void OnNext(Temperature value)
 {
 Console.WriteLine("The temperature is {0}°C at {1:g}", 
value.Degrees, value.Date);
 if (first)
 {
 last = value;
 first = false;
 }
 else
 {
 Console.WriteLine(" Change: {0}° in {1:g}", value.Degrees -
last.Degrees,
 
value.Date.ToUniversalTime() - last.Date.ToUniversalTime());
 }
 }
}
Consulte também
IObserver<T>
Padrão de design do observador
Como implementar um provedor
Práticas recomendadas para o padrão de design do observador
De <https://docs.microsoft.com/pt-br/dotnet/standard/events/how-to-implement-an-observer> 
 Página 29 de Padrao Observer 
IObserver<T> Interface
Definition
Namespace:
System
Assemblies:
System.Runtime.dll, mscorlib.dll, netstandard.dll
Provides a mechanism for receiving push-based notifications.
C#Copiar
public interface IObserver<in T>
Type Parameters
T
The object that provides notification information.
Derived
System.Web.Hosting.LowPhysicalMemoryObserver
System.Web.Hosting.RecycleLimitObserver
Examples
The following example illustrates the observer design pattern. It defines 
a Location class that contains latitude and longitude information.
C#Copiar
public struct Location
{
 double lat, lon;
public Location(double latitude, double longitude)
 {
 this.lat = latitude;
 this.lon = longitude;
 }
public double Latitude
 { get { return this.lat; } }
public double Longitude
 { get { return this.lon; } }
}
The LocationReporter class provides the IObserver<T> implementation. It displays 
information about the current location to the console. Its constructor includes 
a name parameter, which allows the LocationReporter instance to identify itself in 
its string output. It also includes a Subscribe method, which wraps a call to the 
provider's Subscribemethod. This enables the method to assign the 
returned IDisposable reference to a private variable. The LocationReporter class 
also includes an Unsubscribe method, which calls the IDisposable.Dispose method 
of the object returned by the IObservable<T>.Subscribe method. The following code 
defines the LocationReporter class.
C#Copiar
using System;
public class LocationReporter : IObserver<Location>
terça-feira, 24 de abril de 2018 10:07
 Página 30 de Padrao Observer 
public class LocationReporter : IObserver<Location>
{
 private IDisposable unsubscriber;
 private string instName;
public LocationReporter(string name)
 {
 this.instName = name;
 }
public string Name
 { get{ return this.instName; } }
public virtual void Subscribe(IObservable<Location> provider)
 {
 if (provider != null) 
 unsubscriber = provider.Subscribe(this);
 }
public virtual void OnCompleted()
 {
 Console.WriteLine("The Location Tracker has completed transmitting 
data to {0}.", this.Name);
 this.Unsubscribe();
 }
public virtual void OnError(Exception e)
 {
 Console.WriteLine("{0}: The location cannot be determined.", 
this.Name);
 }
public virtual void OnNext(Location value)
 {
 Console.WriteLine("{2}: The current location is {0}, {1}", 
value.Latitude, value.Longitude, this.Name);
 }
public virtual void Unsubscribe()
 {
 unsubscriber.Dispose();
 }
}
The LocationTracker class provides the IObservable<T> implementation. 
Its TrackLocation method is passed a nullable Location object that contains the 
latitude and longitude data. If the Location value is not null, 
the TrackLocation method calls the OnNext method of each observer.
C#Copiar
public class LocationTracker : IObservable<Location>
{
 public LocationTracker()
 {
 observers = new List<IObserver<Location>>();
 }
private List<IObserver<Location>> observers;
public IDisposable Subscribe(IObserver<Location> observer) 
 {
 if (! observers.Contains(observer)) 
 observers.Add(observer);
 return new Unsubscriber(observers, observer);
 }
private class Unsubscriber : IDisposable
 Página 31 de Padrao Observer 
private class Unsubscriber : IDisposable
 {
 private List<IObserver<Location>>_observers;
 private IObserver<Location> _observer;
public Unsubscriber(List<IObserver<Location>> observers, 
IObserver<Location> observer)
 {
 this._observers = observers;
 this._observer = observer;
 }
public void Dispose()
 {
 if (_observer != null && _observers.Contains(_observer))
 _observers.Remove(_observer);
 }
 }
public void TrackLocation(Nullable<Location> loc)
 {
 foreach (var observer in observers) {
 if (! loc.HasValue)
 observer.OnError(new LocationUnknownException());
 else
 observer.OnNext(loc.Value);
 }
 }
public void EndTransmission()
 {
 foreach (var observer in observers.ToArray())
 if (observers.Contains(observer))
 observer.OnCompleted();
observers.Clear();
 }
}
If the Location value is null, the TrackLocation method instantiates 
a LocationNotFoundException object, which is shown in the following example. It 
then calls each observer's OnError method and passes it 
the LocationNotFoundException object. Note 
that LocationNotFoundException derives from Exception but does not add any 
new members.
C#Copiar
public class LocationUnknownException : Exception
{
 internal LocationUnknownException() 
 { }
}
Observers register to receive notifications from a TrackLocation object by calling 
its IObservable<T>.Subscribemethod, which assigns a reference to the observer 
object to a private generic List<T> object. The method returns 
an Unsubscriber object, which is an IDisposable implementation that enables 
observers to stop receiving notifications. The LocationTracker class also includes 
an EndTransmission method. When no further location data is available, the 
method calls each observer's OnCompleted method and then clears the internal list 
of observers.
The following code then instantiates the provider and the observer.
C#Copiar
 Página 32 de Padrao Observer 
C#Copiar
using System;
class Program
{
 static void Main(string[] args)
 {
 // Define a provider and two observers.
 LocationTracker provider = new LocationTracker();
 LocationReporter reporter1 = new LocationReporter("FixedGPS");
 reporter1.Subscribe(provider);
 LocationReporter reporter2 = new LocationReporter("MobileGPS");
 reporter2.Subscribe(provider);
provider.TrackLocation(newLocation(47.6456, -122.1312));
 reporter1.Unsubscribe();
 provider.TrackLocation(new Location(47.6677, -122.1199));
 provider.TrackLocation(null);
 provider.EndTransmission();
 }
}
// The example displays output similar to the following:
// FixedGPS: The current location is 47.6456, -122.1312
// MobileGPS: The current location is 47.6456, -122.1312
// MobileGPS: The current location is 47.6677, -122.1199
// MobileGPS: The location cannot be determined.
// The Location Tracker has completed transmitting data to MobileGPS.
Remarks
The IObserver<T> and IObservable<T> interfaces provide a generalized mechanism 
for push-based notification, also known as the observer design pattern. 
The IObservable<T> interface represents the class that sends notifications (the 
provider); the IObserver<T> interface represents the class that receives them (the 
observer). T represents the class that provides the notification information.
An IObserver<T> implementation arranges to receive notifications from a provider 
(an IObservable<T>implementation) by passing an instance of itself to the 
provider's IObservable<T>.Subscribe method. This method returns 
an IDisposable object that can be used to unsubscribe the observer before the 
provider finishes sending notifications.
The OnNext method, which is typically called by the provider to supply the 
observer with new data or state information.
•
The OnError method, which is typically called by the provider to indicate that 
data is unavailable, inaccessible, or corrupted, or that the provider has 
experienced some other error condition.
•
The OnCompleted method, which is typically called by the provider to indicate 
that it has finished sending notifications to observers.
•
The IObserver<T> interface defines the following three methods that the observer 
must implement:
Methods
OnCompleted() Notifies the observer that the provider has finished sending push-based 
notifications.
OnError(Exceptio
n)
Notifies the observer that the provider has experienced an error 
condition.
 Página 33 de Padrao Observer 
OnNext(T) Provides the observer with new data.
Applies to
.NET Core
2.1 Preview 2, 2.0, 1.1, 1.0
.NET Framework
4.7.2, 4.7.1, 4.7, 4.6.2, 4.6.1, 4.6, 4.5.2, 4.5.1, 4.5
.NET Standard
2.0, 1.6, 1.5, 1.4, 1.3, 1.2, 1.1, 1.0
Xamarin.Android
7.1
Xamarin.iOS
10.8
Xamarin.Mac
3.0
IObservable<T>•
See Also
De <https://docs.microsoft.com/pt-br/dotnet/api/system.iobserver-1?view=netframework-4.7.2> 
=================================================================
TRADUÇÃO
IObserver <T> interface
Definição
Namespace:
Sistema
Assembléias:
System.Runtime.dll, mscorlib.dll, netstandard.dll
Fornece um mecanismo para receber notificações baseadas em push.
C #Copiar
public interface IObserver<in T>
Parâmetros de tipo
T
O objeto que fornece informações de notificação.
Derivado
Sistema. Rede. Hospedagem. Observador de baixa memória física
Sistema. Rede. Hospedagem. Observador de Limite de Reciclagem
Exemplos
 Página 34 de Padrao Observer 
Exemplos
O exemplo a seguir ilustra o padrão de design do observador. Define 
uma Locationclasse que contém informações sobre latitude e longitude.
C #Copiar
public struct Location
{
 double lat, lon;
public Location(double latitude, double longitude)
 {
 this.lat = latitude;
 this.lon = longitude;
 }
public double Latitude
 { get { return this.lat; } }
public double Longitude
 { get { return this.lon; } }
}
A LocationReporterclasse fornece a implementação do IObserver <T> . Ele exibe 
informações sobre o local atual no console. Seu construtor inclui um nameparâmetro, 
que permite que a LocationReporterinstância se identifique em sua saída de 
cadeia. Ele também inclui um Subscribemétodo, que envolve uma chamada para 
o método de inscrição do provedor . Isso permite que o método atribua 
a referência IDisposable retornada a uma variável 
privada. A LocationReporterclasse também inclui um Unsubscribemétodo, que 
chama o método IDisposable.Dispose do objeto retornado pelo método IObservable 
<T> .Subscribe . O código a seguir define a LocationReporterclasse.
C #Copiar
using System;
public class LocationReporter : IObserver<Location>
{
 private IDisposable unsubscriber;
 private string instName;
public LocationReporter(string name)
 {
 this.instName = name;
 }
public string Name
 { get{ return this.instName; } }
public virtual void Subscribe(IObservable<Location> provider)
 {
 if (provider != null) 
 unsubscriber = provider.Subscribe(this);
 }
public virtual void OnCompleted()
 {
 Console.WriteLine("The Location Tracker has completed transmitting 
data to {0}.", this.Name);
 this.Unsubscribe();
 }
public virtual void OnError(Exception e)
 {
 Console.WriteLine("{0}: The location cannot be determined.", 
this.Name);
 Página 35 de Padrao Observer 
this.Name);
 }
public virtual void OnNext(Location value)
 {
 Console.WriteLine("{2}: The current location is {0}, {1}", 
value.Latitude, value.Longitude, this.Name);
 }
public virtual void Unsubscribe()
 {
 unsubscriber.Dispose();
 }
}
A LocationTrackerclasse fornece a implementação IObservable 
<T> . Seu TrackLocationmétodo é passado um Locationobjeto anulável que 
contém os dados de latitude e longitude. Se o Locationvalor não for null, 
o TrackLocationmétodo chama o método OnNext de cada observador.
C #Copiar
public class LocationTracker : IObservable<Location>
{
 public LocationTracker()
 {
 observers = new List<IObserver<Location>>();
 }
private List<IObserver<Location>> observers;
public IDisposable Subscribe(IObserver<Location> observer) 
 {
 if (! observers.Contains(observer)) 
 observers.Add(observer);
 return new Unsubscriber(observers, observer);
 }
private class Unsubscriber : IDisposable
 {
 private List<IObserver<Location>>_observers;
 private IObserver<Location> _observer;
public Unsubscriber(List<IObserver<Location>> observers, 
IObserver<Location> observer)
 {
 this._observers = observers;
 this._observer = observer;
 }
public void Dispose()
 {
 if (_observer != null && _observers.Contains(_observer))
 _observers.Remove(_observer);
 }
 }
public void TrackLocation(Nullable<Location> loc)
 {
 foreach (var observer in observers) {
 if (! loc.HasValue)
 observer.OnError(new LocationUnknownException());
 else
 observer.OnNext(loc.Value);
 }
 }
 Página 36 de Padrao Observer 
 }
public void EndTransmission()
 {
 foreach (var observer in observers.ToArray())
 if (observers.Contains(observer))
 observer.OnCompleted();
observers.Clear();
 }
}
Se o Locationvalor for null, o TrackLocationmétodo instancia 
um LocationNotFoundExceptionobjeto, mostrado no exemplo a seguir. Em 
seguida, ele chama o método OnError de cada observador e passa 
o LocationNotFoundExceptionobjeto para ele. Observe 
que LocationNotFoundExceptionderiva da exceção, mas não adiciona novos 
membros.
C #Copiar
public class LocationUnknownException : Exception
{
 internal LocationUnknownException() 
 { }
}
Observadores registram para receber notificações de um TrackLocationobjeto 
chamando seu método IObservable <T> .Subscribe , que atribui uma referência ao 
objeto observador a um objeto List <T> genérico particular . O métodoretorna 
um Unsubscriberobjeto, que é uma implementação descartável que permite que os 
observadores parem de receber notificações. A LocationTrackerclasse também 
inclui um EndTransmissionmétodo. Quando não há mais dados de localização 
disponíveis, o método chama o método OnCompleted de cada observador e, em 
seguida, limpa a lista interna de observadores.
O código a seguir instancia o provedor e o observador.
C #Copiar
using System;
class Program
{
 static void Main(string[] args)
 {
 // Define a provider and two observers.
 LocationTracker provider = new LocationTracker();
 LocationReporter reporter1 = new LocationReporter("FixedGPS");
 reporter1.Subscribe(provider);
 LocationReporter reporter2 = new LocationReporter("MobileGPS");
 reporter2.Subscribe(provider);
provider.TrackLocation(new Location(47.6456, -122.1312));
 reporter1.Unsubscribe();
 provider.TrackLocation(new Location(47.6677, -122.1199));
 provider.TrackLocation(null);
 provider.EndTransmission();
 }
}
// The example displays output similar to the following:
// FixedGPS: The current location is 47.6456, -122.1312
// MobileGPS: The current location is 47.6456, -122.1312
// MobileGPS: The current location is 47.6677, -122.1199
// MobileGPS: The location cannot be determined.
// The Location Tracker has completed transmitting data to MobileGPS.
 Página 37 de Padrao Observer 
// The Location Tracker has completed transmitting data to MobileGPS.
Observações
As interfaces IObserver <T> e IObservable <T> fornecem um mecanismo 
generalizado para notificação baseada em push, também conhecido como padrão 
de design do observador. A interface IObservable <T> representa a classe que 
envia notificações (o provedor); a interface IObserver <T> representa a classe que 
os recebe (o observador). Trepresenta a classe que fornece as informações de 
notificação.
Uma implementação IObserver <T> organiza para receber notificações de um 
provedor (uma implementação IObservable <T> ) passando uma instância de si 
mesmo para o método IObservable <T> .Subscribe do provedor . Esse método 
retorna um objeto IDisposable que pode ser usado para cancelar a assinatura do 
observador antes que o provedor termine o envio de notificações.
O método OnNext , que é normalmente chamado pelo provedor para fornecer 
ao observador novos dados ou informações de estado.
•
O método OnError , que é normalmente chamado pelo provedor para indicar 
que os dados estão indisponíveis, inacessíveis ou corrompidos, ou que o 
provedor experimentou alguma outra condição de erro.
•
O método OnCompleted , que é normalmente chamado pelo provedor para 
indicar que ele concluiu o envio de notificações para os observadores.
•
A interface IObserver <T> define os três métodos a seguir que o observador deve 
implementar:
Métodos
Em concluído () Notifica o observador que o provedor terminou o envio de notificações 
baseadas em push.
Em erro 
(exceção)
Notifica o observador que o provedor teve uma condição de erro.
Na próxima (T) Fornece o observador com novos dados.
Aplica-se a
.NET Core
2.1 Visualização 2 , 2.0 , 1.1 , 1.0
.NET Framework
4.7.2 , 4.7.1 , 4.7 , 4.6.2 , 4.6.1 , 4.6 , 4.5.2 , 4.5.1 , 4.5
Padrão .NET
2,0 , 1,6 , 1,5 , 1,4 , 1,3 , 1,2 , 1,1 , 1,0
Xamarin.Android
7,1
Xamarin.iOS
10,8
Xamarin.Mac
3,0
 Página 38 de Padrao Observer 
3,0
IObservable <T>•
Veja também
De <https://docs.microsoft.com/pt-br/dotnet/api/system.iobserver-1?view=netframework-4.7.2> 
 Página 39 de Padrao Observer 
IObservable<T> Interface
Definition
Namespace:
System
Assemblies:
System.Runtime.dll, mscorlib.dll, netstandard.dll
Defines a provider for push-based notification.
C#Copiar
public interface IObservable<out T>
Type Parameters
T
The object that provides notification information.
Derived
System.Diagnostics.DiagnosticListener
System.Web.Hosting.AspNetMemoryMonitor
System.Web.Hosting.AspNetMemoryMonitor
Examples
The following example illustrates the observer design pattern. It defines 
a Location class that contains latitude and longitude information.
C#Copiar
public struct Location
{
 double lat, lon;
public Location(double latitude, double longitude)
 {
 this.lat = latitude;
 this.lon = longitude;
 }
public double Latitude
 { get { return this.lat; } }
public double Longitude
 { get { return this.lon; } }
}
The LocationTracker class provides the IObservable<T> implementation. 
Its TrackLocation method is passed a nullable Location object that contains the 
latitude and longitude data. If the Location value is not null, 
the TrackLocation method calls the OnNext method of each observer.
C#Copiar
public class LocationTracker : IObservable<Location>
{
 public LocationTracker()
 {
 observers = new List<IObserver<Location>>();
 }
terça-feira, 24 de abril de 2018 10:08
 Página 40 de Padrao Observer 
 }
private List<IObserver<Location>> observers;
public IDisposable Subscribe(IObserver<Location> observer) 
 {
 if (! observers.Contains(observer)) 
 observers.Add(observer);
 return new Unsubscriber(observers, observer);
 }
private class Unsubscriber : IDisposable
 {
 private List<IObserver<Location>>_observers;
 private IObserver<Location> _observer;
public Unsubscriber(List<IObserver<Location>> observers, 
IObserver<Location> observer)
 {
 this._observers = observers;
 this._observer = observer;
 }
public void Dispose()
 {
 if (_observer != null && _observers.Contains(_observer))
 _observers.Remove(_observer);
 }
 }
public void TrackLocation(Nullable<Location> loc)
 {
 foreach (var observer in observers) {
 if (! loc.HasValue)
 observer.OnError(new LocationUnknownException());
 else
 observer.OnNext(loc.Value);
 }
 }
public void EndTransmission()
 {
 foreach (var observer in observers.ToArray())
 if (observers.Contains(observer))
 observer.OnCompleted();
observers.Clear();
 }
}
If the Location value is null, the TrackLocation method instantiates 
a LocationUnknownException object, which is shown in the following example. It 
then calls each observer's OnError method and passes it 
the LocationUnknownException object. Note 
that LocationUnknownException derives from Exception, but does not add any new 
members.
C#Copiar
public class LocationUnknownException : Exception
{
 internal LocationUnknownException() 
 { }
}
Observers register to receive notifications from a TrackLocation object by calling 
its IObservable<T>.Subscribemethod, which assigns a reference to the observer 
 Página 41 de Padrao Observer 
its IObservable<T>.Subscribemethod, which assigns a reference to the observer 
object to a private generic List<T> object. The method returns 
an Unsubscriber object, which is an IDisposable implementation that enables 
observers to stop receiving notifications. The LocationTracker class also includes 
an EndTransmission method. When no further location data is available, the 
method calls each observer's OnCompleted method and then clears the internal list 
of observers.
In this example, the LocationReporter class provides 
the IObserver<T> implementation. It displays information about the current location 
to the console. Its constructor includes a name parameter, which enables 
the LocationReporter instance to identify itself in its string output. It also includesa Subscribe method, which wraps a call to the provider's Subscribe method. This 
allows the method to assign the returned IDisposable reference to a private variable. 
The LocationReporter class also includes an Unsubscribe method, which calls 
the IDisposable.Dispose method of the object that is returned by 
the IObservable<T>.Subscribe method. The following code defines 
the LocationReporter class.
C#Copiar
using System;
public class LocationReporter : IObserver<Location>
{
 private IDisposable unsubscriber;
 private string instName;
public LocationReporter(string name)
 {
 this.instName = name;
 }
public string Name
 { get{ return this.instName; } }
public virtual void Subscribe(IObservable<Location> provider)
 {
 if (provider != null) 
 unsubscriber = provider.Subscribe(this);
 }
public virtual void OnCompleted()
 {
 Console.WriteLine("The Location Tracker has completed transmitting 
data to {0}.", this.Name);
 this.Unsubscribe();
 }
public virtual void OnError(Exception e)
 {
 Console.WriteLine("{0}: The location cannot be determined.", 
this.Name);
 }
public virtual void OnNext(Location value)
 {
 Console.WriteLine("{2}: The current location is {0}, {1}", 
value.Latitude, value.Longitude, this.Name);
 }
public virtual void Unsubscribe()
 {
 unsubscriber.Dispose();
 }
}
 Página 42 de Padrao Observer 
}
The following code then instantiates the provider and the observer.
C#Copiar
using System;
class Program
{
 static void Main(string[] args)
 {
 // Define a provider and two observers.
 LocationTracker provider = new LocationTracker();
 LocationReporter reporter1 = new LocationReporter("FixedGPS");
 reporter1.Subscribe(provider);
 LocationReporter reporter2 = new LocationReporter("MobileGPS");
 reporter2.Subscribe(provider);
provider.TrackLocation(new Location(47.6456, -122.1312));
 reporter1.Unsubscribe();
 provider.TrackLocation(new Location(47.6677, -122.1199));
 provider.TrackLocation(null);
 provider.EndTransmission();
 }
}
// The example displays output similar to the following:
// FixedGPS: The current location is 47.6456, -122.1312
// MobileGPS: The current location is 47.6456, -122.1312
// MobileGPS: The current location is 47.6677, -122.1199
// MobileGPS: The location cannot be determined.
// The Location Tracker has completed transmitting data to MobileGPS.
Remarks
The IObserver<T> and IObservable<T> interfaces provide a generalized mechanism 
for push-based notification, also known as the observer design pattern. 
The IObservable<T> interface represents the class that sends notifications (the 
provider); the IObserver<T> interface represents the class that receives them (the 
observer). T represents the class that provides the notification information. In some 
push-based notifications, the IObserver<T> implementation and T can represent the 
same type.
The provider must implement a single method, Subscribe, that indicates that an 
observer wants to receive push-based notifications. Callers to the method pass an 
instance of the observer. The method returns an IDisposableimplementation that 
enables observers to cancel notifications at any time before the provider has stopped 
sending them.
At any given time, a given provider may have zero, one, or multiple observers. The 
provider is responsible for storing references to observers and ensuring that they are 
valid before it sends notifications. The IObservable<T> interface does not make any 
assumptions about the number of observers or the order in which notifications are 
sent.
The current data. The provider can call the IObserver<T>.OnNext method to 
pass the observer a T object that has current data, changed data, or fresh data.
•
An error condition. The provider can call the IObserver<T>.OnError method to 
notify the observer that some error condition has occurred.
•
No further data. The provider can call the IObserver<T>.OnCompleted method 
to notify the observer that it has finished sending notifications.
•
The provider sends the following three kinds of notifications to the observer by 
calling IObserver<T> methods:
 Página 43 de Padrao Observer 
to notify the observer that it has finished sending notifications.
Methods
Subscribe(IObserver<T>) Notifies the provider that an observer is to receive notifications.
Applies to
.NET Core
2.1 Preview 2, 2.0, 1.1, 1.0
.NET Framework
4.7.2, 4.7.1, 4.7, 4.6.2, 4.6.1, 4.6, 4.5.2, 4.5.1, 4.5
.NET Standard
2.0, 1.6, 1.5, 1.4, 1.3, 1.2, 1.1, 1.0
Xamarin.Android
7.1
Xamarin.iOS
10.8
Xamarin.Mac
3.0
IObserver<T>•
See Also
De <https://docs.microsoft.com/pt-br/dotnet/api/system.iobservable-1?view=netframework-4.7.2> 
===================================================================
TRADUZIDO:
IObservable <T> Interface
Definição
Namespace:
Sistema
Assembléias:
System.Runtime.dll, mscorlib.dll, netstandard.dll
Define um provedor para notificação baseada em push.
C #Copiar
public interface IObservable<out T>
Parâmetros de tipo
T
O objeto que fornece informações de notificação.
Derivado
 Página 44 de Padrao Observer 
Derivado
Sistema. Diagnóstico Ouvinte de diagnóstico
Sistema. Rede. Hospedagem. Monitor de memória Asp Net
Sistema. Rede. Hospedagem. Monitor de memória Asp Net
Exemplos
O exemplo a seguir ilustra o padrão de design do observador. Define 
uma Locationclasse que contém informações sobre latitude e longitude.
C #Copiar
public struct Location
{
 double lat, lon;
public Location(double latitude, double longitude)
 {
 this.lat = latitude;
 this.lon = longitude;
 }
public double Latitude
 { get { return this.lat; } }
public double Longitude
 { get { return this.lon; } }
}
A LocationTrackerclasse fornece a implementação IObservable 
<T> . Seu TrackLocationmétodo é passado um Locationobjeto anulável que 
contém os dados de latitude e longitude. Se o Locationvalor não for null, 
o TrackLocationmétodo chama o método OnNext de cada observador.
C #Copiar
public class LocationTracker : IObservable<Location>
{
 public LocationTracker()
 {
 observers = new List<IObserver<Location>>();
 }
private List<IObserver<Location>> observers;
public IDisposable Subscribe(IObserver<Location> observer) 
 {
 if (! observers.Contains(observer)) 
 observers.Add(observer);
 return new Unsubscriber(observers, observer);
 }
private class Unsubscriber : IDisposable
 {
 private List<IObserver<Location>>_observers;
 private IObserver<Location> _observer;
public Unsubscriber(List<IObserver<Location>> observers, 
IObserver<Location> observer)
 {
 this._observers = observers;
 this._observer = observer;
 }
public void Dispose()
 {
 if (_observer != null && _observers.Contains(_observer))
 Página 45 de Padrao Observer 
 if (_observer != null && _observers.Contains(_observer))
 _observers.Remove(_observer);
 }
 }
public void TrackLocation(Nullable<Location> loc)
 {
 foreach (var observer in observers) {
 if (! loc.HasValue)
 observer.OnError(new LocationUnknownException());
 else
 observer.OnNext(loc.Value);
 }
 }
public void EndTransmission()
 {
 foreach (var observer in observers.ToArray())
 if (observers.Contains(observer))
 observer.OnCompleted();
observers.Clear();}
}
Se o Locationvalor for null, o TrackLocationmétodo instancia 
um LocationUnknownExceptionobjeto, mostrado no exemplo a seguir. Em 
seguida, ele chama o método OnError de cada observador e passa 
o LocationUnknownExceptionobjeto para ele. Observe 
que LocationUnknownExceptionderiva de exceção , mas não adiciona novos 
membros.
C #Copiar
public class LocationUnknownException : Exception
{
 internal LocationUnknownException() 
 { }
}
Observadores registram para receber notificações de um TrackLocationobjeto 
chamando seu método IObservable <T> .Subscribe , que atribui uma referência ao 
objeto observador a um objeto List <T> genérico particular . O método retorna 
um Unsubscriberobjeto, que é uma implementação descartável que permite que os 
observadores parem de receber notificações. A LocationTrackerclasse também 
inclui um EndTransmissionmétodo. Quando não há mais dados de localização 
disponíveis, o método chama o método OnCompleted de cada observador e, em 
seguida, limpa a lista interna de observadores.
Neste exemplo, a LocationReporterclasse fornece a implementação IObserver 
<T> . Ele exibe informações sobre o local atual no console. Seu construtor inclui 
um nameparâmetro, que permite que a LocationReporterinstância se identifique 
em sua saída de cadeia. Ele também inclui um Subscribemétodo, que envolve uma 
chamada para o método de inscrição do provedor . Isso permite que o método 
atribua a referência IDisposable retornada a uma variável 
privada. A LocationReporterclasse também inclui um Unsubscribemétodo, que 
chama o método IDisposable.Dispose do objeto retornado pelo método IObservable 
<T> .Subscribe . O código a seguir define a LocationReporterclasse.
C #Copiar
using System;
public class LocationReporter : IObserver<Location>
{
 private IDisposable unsubscriber;
 Página 46 de Padrao Observer 
 private IDisposable unsubscriber;
 private string instName;
public LocationReporter(string name)
 {
 this.instName = name;
 }
public string Name
 { get{ return this.instName; } }
public virtual void Subscribe(IObservable<Location> provider)
 {
 if (provider != null) 
 unsubscriber = provider.Subscribe(this);
 }
public virtual void OnCompleted()
 {
 Console.WriteLine("The Location Tracker has completed transmitting 
data to {0}.", this.Name);
 this.Unsubscribe();
 }
public virtual void OnError(Exception e)
 {
 Console.WriteLine("{0}: The location cannot be determined.", 
this.Name);
 }
public virtual void OnNext(Location value)
 {
 Console.WriteLine("{2}: The current location is {0}, {1}", 
value.Latitude, value.Longitude, this.Name);
 }
public virtual void Unsubscribe()
 {
 unsubscriber.Dispose();
 }
}
O código a seguir instancia o provedor e o observador.
C #Copiar
using System;
class Program
{
 static void Main(string[] args)
 {
 // Define a provider and two observers.
 LocationTracker provider = new LocationTracker();
 LocationReporter reporter1 = new LocationReporter("FixedGPS");
 reporter1.Subscribe(provider);
 LocationReporter reporter2 = new LocationReporter("MobileGPS");
 reporter2.Subscribe(provider);
provider.TrackLocation(new Location(47.6456, -122.1312));
 reporter1.Unsubscribe();
 provider.TrackLocation(new Location(47.6677, -122.1199));
 provider.TrackLocation(null);
 provider.EndTransmission();
 }
}
// The example displays output similar to the following:
 Página 47 de Padrao Observer 
// The example displays output similar to the following:
// FixedGPS: The current location is 47.6456, -122.1312
// MobileGPS: The current location is 47.6456, -122.1312
// MobileGPS: The current location is 47.6677, -122.1199
// MobileGPS: The location cannot be determined.
// The Location Tracker has completed transmitting data to MobileGPS.
Observações
As interfaces IObserver <T> e IObservable <T> fornecem um mecanismo 
generalizado para notificação baseada em push, também conhecido como padrão 
de design do observador. A interface IObservable <T> representa a classe que 
envia notificações (o provedor); a interface IObserver <T> representa a classe que 
os recebe (o observador). Trepresenta a classe que fornece as informações de 
notificação. Em algumas notificações baseadas em push, a implementação 
IObserver <T> e Tpode representar o mesmo tipo.
O provedor deve implementar um único método, Subscribe , que indica que um 
observador deseja receber notificações baseadas em push. Os chamadores para o 
método passam uma instância do observador. O método retorna 
uma implementação IDisposable que permite que os observadores cancelem as 
notificações a qualquer momento antes que o provedor pare de enviá-las.
A qualquer momento, um determinado provedor pode ter zero, um ou vários 
observadores. O provedor é responsável por armazenar referências aos 
observadores e garantir que elas sejam válidas antes de enviar 
notificações. A interface IObservable <T> não faz nenhuma suposição sobre o 
número de observadores ou a ordem na qual as notificações são enviadas.
Os dados atuais. O provedor pode chamar o método IObserver 
<T> .OnNext para passar ao observador um Tobjeto que tenha dados atuais, 
dados alterados ou dados novos.
•
Uma condição de erro. O provedor pode chamar o método IObserver 
<T> .OnError para notificar o observador que alguma condição de erro ocorreu.
•
Não há mais dados. O provedor pode chamar o método IObserver 
<T> .OnCompleted para notificar o observador que ele terminou o envio de 
notificações.
•
O provedor envia os seguintes três tipos de notificações para o observador 
chamando métodos IObserver <T> :
Métodos
Inscreva-se (IObserver 
<T>)
Notifica o provedor que um observador deve receber 
notificações.
Aplica-se a
.NET Core
2.1 Visualização 2 , 2.0 , 1.1 , 1.0
.NET Framework
4.7.2 , 4.7.1 , 4.7 , 4.6.2 , 4.6.1 , 4.6 , 4.5.2 , 4.5.1 , 4.5
Padrão .NET
2,0 , 1,6 , 1,5 , 1,4 , 1,3 , 1,2 , 1,1 , 1,0
 Página 48 de Padrao Observer 
Xamarin.Android
7,1
Xamarin.iOS
10,8
Xamarin.Mac
3,0
IObserver <T>•
Veja também
De <https://docs.microsoft.com/pt-br/dotnet/api/system.iobservable-1?view=netframework-4.7.2> 
 Página 49 de Padrao Observer 
Implementando um notificador de eventos
01/06/2015ROBSON CASTILHO
Olá, pessoal
No artigo de hoje, veremos na prática a implementação de um notificador 
de eventos (o famoso padrão “Observer”) fazendo uso de um container de 
DI. A solução proposta é flexível, utilizando boas práticas de design e 
arquitetura de software.
____________________________
Nota: este é um artigo avançado, pois utiliza-se de padrões como 
Observer e Ambient Context, conceitos como Dependency Injection, 
CompositionRoot e Princípio da Inversão de Dependência e práticas de 
teste como mocks. Portanto, esses conceitos são necessários para um 
melhor entendimento do “porquê” das coisas. O artigo fornece diversas 
referências para todos eles.
____________________________
Vamos lá!
NOTIFICANDO EVENTOS
Um notificador de eventos é uma variação do conhecido design 
pattern Publish/Subscribe (ou Observer). Seguindo a definição do 
padrão à risca, o “publisher” (nosso Notificador) notifica todos os 
interessados (os “observers”) sempre que aquele muda seu estado.
É uma boa solução quando temos uma relação de um para muitos entre 
objetos e não queremos acoplá-los por se tratarem de objetos de outras 
camadas e para deixar o notificador mais flexível em relação aos seus 
“observers”.
Obs. 1: No nosso caso, o notificador não notificará mudança de estado –
veremosque ele nem sequer possui estado – e sim um evento ocorrido em nossa 
aplicação.
Obs. 2: O evento, no caso deste artigo, será um evento de domínio, ou 
seja, uma situação ocorrida em nossa lógica de negócio e que precisa ser 
comunicada a outros contextos (que podem ser outras aplicações). No 
entanto, a mesma ideia mostrada no artigo pode ser utilizada para notificar 
outros tipos de eventos (de outras camadas).
IMPLEMENTANDO UM NOTIFICADOR BASEADO EM UM CONTAINER 
DE DI
Vendo a definição formal do padrão Observer no link mais acima, vocês 
podem notar que o “publisher/subject” expõe métodos para adicionar e 
remover os “observers” que deverão ser notificados. Em outras palavras, o 
notificador mantém a lista de “observers”.
No exemplo deste artigo, a implementação adotada faz uso de um 
container de Dependency Injection para localizar seus “observers” e poder 
notificá-los, dispensando assim que o notificador conheça a lista de seus 
“observers”.
Vejamos como fica o código:
1
2
// o "publisher/subject"
public class NotificadorDeEventosDeDominio
terça-feira, 24 de abril de 2018 10:22
 Página 50 de Padrao Observer 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class NotificadorDeEventosDeDominio
{
 public static void NotificarSobre<T>(T eventoDeDominio) where T : 
IEventoDeDominio
 {
 foreach (var enderecador in 
this.container.GetAllInstances<IEnderecadorDeEvento<T>>())
 enderecador.Enderecar(eventoDeDominio);
 }
}
// interface de marcação para os eventos de domínio
public interface IEventoDeDominio { }
// o "subscriber/observer"
public interface IEnderecadorDeEvento<T> where T : IEventoDeDominio
{
 void Enderecar(T eventoDeDominio);
}
Algumas observações sobre o código:
O notificador não conhece seus “observers”. Ao invés disso, ele pede ao 
container de DI para localizá-los, ou seja, estamos usando o container 
como um Service Locator. Muita cautela com esse tipo de prática. Não 
espalhe o container por toda sua aplicação, pois além da dependência 
concreta em relação ao container, você estará escondendo todas as 
dependências que suas classes possuem.
•
O container de DI é injetado via construtor e armazenado em um field 
usado no método acima (this.container).
•
Qualquer container de DI de sua preferência pode ser utilizado.•
IEventoDeDominio é apenas uma interface de marcação para 
restringirmos o parâmetro do método e os “observers” para aceitarem 
somente objetos que sejam eventos de domínio.
•
Tanto o notificador como as interfaces usadas estão na camada de 
domínio, pois estão diretamente relacionados.
•
Um exemplo de uso seria o seguinte:
1
2
3
4
5
6
7
8
9
10
11
public class Despesa
{
 public void Baixar()
 {
 // baixa da despesa ....
 // notificando evento
 NotificadorDeEventosDeDominio
 .NotificarSobre(new DespesaPaga(idDespesa, valorPago));
 }
}
No exemplo acima, uma entidade do domínio, após realizar sua operação 
de baixa, notifica aos interessados a ocorrência do evento DespesaPaga. 
Um “observer” que receberia essa notificação seria qualquer objeto que 
implemente IEnderecadorDeDominio<DespesaPaga>.
ALGUNS PROBLEMAS
A solução mostrada apresenta alguns problemas:
1. Como dito antes, o NotificadorDeEventosDeDominio encontra-se na 
camada de domínio, juntamente com a classe Despesa e demais classes 
que modelam o negócio. Como usamos o container de DI na 
implementação do notificador, somos obrigados a manter uma referência 
do container no domínio, ou seja, o domínio conhece um detalhe técnico (o 
 Página 51 de Padrao Observer 
do container no domínio, ou seja, o domínio conhece um detalhe técnico (o 
container).
De um ponto de vista arquitetural, devemos deixar o domínio o mais 
ignorante possível de detalhes técnicos (mais aqui).
Portanto, precisamos remover essa dependência do domínio para o 
container de DI!
2. Testabilidade! Conseguimos garantir que o estado do objeto Despesa foi 
alterado na baixa mas não conseguimos testar que a notificação realmente 
foi chamada, uma vez que fazemos isso por meio de um 
método estático do notificador.
VERSÃO MELHORADA
Para sanar os problemas acima, precisamos abstrair o notificador de 
eventos, aplicando o Princípio da Inversão de Dependência.
No entanto, quero continuar usando o notificador como um ambient 
context, ou seja, não quero poluir a interface das minhas entidades de 
domínio injetando o notificador via construtor, método ou propriedade.
Vejamos como fica a nova versão, começando pela abstração:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class NotificadorDeEventosDeDominio
{
 private static NotificadorDeEventosDeDominio _notificadorCorrente;
 public static NotificadorDeEventosDeDominio NotificadorCorrente
 {
 get { return _notificadorCorrente; }
 set
 {
 if (value == null)
 throw new ArgumentNullException("value");
 _notificadorCorrente = value;
 }
 }
 public abstract void NotificarSobre<T>(T eventoDeDominio) where T : 
IEventoDeDominio;
}
O notificador concreto é praticamente o anterior, porém herdando da 
abstração acima:
1
2
3
4
5
6
7
8
9
10
public class NotificadorBaseadoEmContainerDeDi : 
NotificadorDeEventosDeDominio
{
 // construtor com injecao do container omitido
 public override void NotificarSobre<T>(T eventoDeDominio)
 {
 foreach (var enderecador in 
this.container.GetAllInstances<IEnderecadorDeEvento<T>>())
 enderecador.Enderecar(eventoDeDominio);
 }
}
Agora, os objetos de domínio passam a depender da abstração e não 
mais do notificador concreto:
1
2
3
4
5
6
public class Despesa
{
 public void Baixar()
 {
 // baixa da despesa ...
 Página 52 de Padrao Observer 
6
7
8
9
10
11
 // notificando evento
 NotificadorDeEventosDeDominio
 .NotificadorCorrente.NotificarSobre(new 
DespesaPaga(idDespesa, valorPago));
 }
}
Sendo assim, podemos mover o notificador concreto do domínio para o 
assembly que faz uso do container de DI para subir a aplicação. Com isso, 
o domínio passa a não conhecer mais o container de DI.
GARANTINDO A TESTABILIDADE
Com a nova versão, podemos testar melhor os objetos de domínio que 
fazem uso do notificador.
Vejamos como fica o teste da entidade Despesa, que verifica se o 
notificador foi realmente chamado (e com o evento correto):
1
2
3
4
5
6
7
8
9
10
11
12
13
[Test]
public void Deve_notificar_sobre_baixa_da_despesa()
{
 var notificadorDeEventosDeDominioMock = new 
Mock<NotificadorDeEventosDeDominio>();
 NotificadorDeEventosDeDominio.NotificadorCorrente = 
notificadorDeEventosDeDominioMock.Object;
 var despesa = new Despesa();
 despesa.Baixar();
 var despesaPaga = (new DespesaPaga(100, 
100.50)).AsSource().OfLikeness<DespesaPaga>().CreateProxy();
 notificadorDeEventosDeDominioMock.Verify(mock => 
mock.NotificarSobre(despesaPaga), Times.Once);
}
Vejam que, para fins de teste, configuramos o NotificadorCorrente com um 
mock ao invés de usarmos o notificador concreto e fazemos a asserção do 
teste verificando que o método NotificarSobre() foi realmente chamado 
com o evento correto e somente uma vez.
(Obs.: Neste teste, utilizei a lib SemanticComparison para criar o objeto 
esperado como parâmetro do método. Para saber mais sobre ela, leia meu 
post anterior sobre comparação semântica.)
USANDO O NOTIFICADOR CONCRETO
Ok, usamos um mock como NotificadorCorrente nos testes de unidade. E 
no código de produção? Onde usamos o notificador concreto?
A resposta é simples: configuramos o NotificadorCorrente com o 
notificador concreto no start da aplicação (*)e nunca mais mexemos com 
ele:
1
2
3
var container = ConfigurarContainer();
NotificadorDeEventosDeDominio.NotificadorCorrente =
 new NotificadorBaseadoEmContainerDeDi(container);
(*) Esse local é chamado de CompositionRoot e falei sobre ele na 
minha série sobre Dependency Injection.
Relembrando que o notificador concreto fica junto do container no mesmo 
assembly, que pode ser o assembly referente à camada de apresentação 
ou um específico para o CompositionRoot (o que eu acho mais adequado 
em projetos reais).
E OS OBSERVERS CONCRETOS?
Os observers concretos – aqueles que implementam 
 Página 53 de Padrao Observer 
Os observers concretos – aqueles que implementam 
IEnderecadorDeEvento<T> – ficam na camada correspondente ao seu propósito. 
Se o observer, por exemplo, informa alguma coisa para a view ele ficará na 
camada de apresentação. Outro observer que trata o evento comunicando-se 
com algum serviço externo (e-mail, API REST, messaging) certamente ficará na 
camada de infra-estrutura. E assim por diante.
CONCLUINDO
Vimos, passo-a-passo, como criar um notificador de eventos (padrão 
Observer) usando um container de DI em sua implementação.
A solução mostrada apresenta baixo acoplamento entre os módulos, o que 
garante testabilidade dos clientes do notificador e atende a regra de 
dependências entre camadas (sempre da mais externa para a mais 
interna).
Foi um artigo avançado, que exigiu conhecimento de diversos padrões de 
design e arquitetura de software, mas espero ter conseguido passar a 
ideia.
Para reforçar o entendimento, disponibilizei no meu github o código do 
artigojuntamente com um pequeno exemplo funcional de uma app console, 
que faz uso de tudo que foi visto aqui.
Espero que tenham gostado. Comentários, dúvidas, críticas? Só escrever!
[]s e até a próxima!
Avalie isto:
3 Votos
Compartilhe:
24Compartilhar no Facebook(abre em nova janela)24•
Clique para compartilhar no Twitter(abre em nova janela)•
Clique para compartilhar no LinkedIn(abre em nova janela)•
Clique para imprimir(abre em nova janela)•
Conhecendo Design Patterns e o padrão StrategyEm "patterns"
Sobre camadas, cebolas e hexágonos...Em "Arquitetura de Software"
Como foi o workshop com Ralph Johnson do GoFEm "carreira"
Categorias: .net, Arquitetura de Software Tags: arquitetura de software, design 
patterns, DI containers, domain events, observer
Navegação de Posts
← Comparando objetos semanticamente
FluentBuilder – Meu primeiro pacote Nuget→
4 comentários em “Implementando um 
notificador de eventos”
 Página 54 de Padrao Observer 
Yan Justino disse:
01/06/2015 ÀS 20:38
Parabéns pelo post, Robson! Eu gosto muito do Domain Events. Geralmente 
eu coloco a implemntação dele num Shared Kernel e Interfaceio o container DI. 
Vou experimentar essa abordagem no próximo projeto.
RESPONDER
Robson Castilho disse:
01/06/2015 ÀS 20:46
Olá, Yan
Obrigado.
Então, já fiz isso mas eliminei essa interface pelo seguinte:
Não acho que faça sentido uma interface pra um container de DI (dado que vc 
so utilizará um e normalmente em um só local da app – o CompositionRoot). 
Além disso, voce teria que coloca-la no dominio (que faz ainda menos sentido pra 
mim) ou numa camada acima (e aí o dominio teria que fazer referencia a alguem mais 
acima, mesmo problema de depender do container, embora não seja o concreto).
Por esses motivos, matei a interface e uso o container concreto (apenas no 
CompositionRoot, em duas ou tres classes).
IMHO!
[]s
(AH..deletei seu outro comentário que era praticamente uma cópia desse :)).
RESPONDER
James Diniz disse:
04/06/2015 ÀS 20:03
Mais um excelente post, parabéns Robson.
RESPONDER
Robson Castilho disse:
04/06/2015 ÀS 20:08
Obrigado, James
De <https://robsoncastilho.com.br/2015/06/01/implementando-um-notificador-de-eventos/> 
 Página 55 de Padrao Observer

Mais conteúdos dessa disciplina