O que são "decoradores" e como são usados?

148

Estou curioso para saber exatamente o que são os decoradores no AngularJS. Não há muitas informações on-line para os decoradores, exceto um resumo na documentação do AngularJS e uma breve (embora interessante) menção em um vídeo do youtube .

Como dizem os caras do Angular, um decorador é:

Decoração de serviço, permite ao decorador interceptar a criação da instância de serviço. A instância retornada pode ser a instância original ou uma nova instância que delega para a instância original.

Realmente não sei o que isso significa e não sei por que você separaria essa lógica do próprio serviço. Por exemplo, se eu quisesse retornar algo diferente sob condições diferentes, passaria argumentos diferentes para as funções relevantes ou usaria outra função que compartilha esse estado privado.

Eu ainda sou meio noob do AngularJS, então tenho certeza de que são apenas ignorância e / ou maus hábitos que aprendi.

Kevin Beal
fonte

Respostas:

219

Um bom caso de uso $provide.decoratoré quando você precisa fazer pequenos "ajustes" em algum serviço de terceiros / upstream, do qual seu módulo depende, enquanto deixa o serviço intacto (porque você não é o proprietário / mantenedor do serviço). Aqui está uma demonstração no plunkr.

tamakisquare
fonte
6
Exemplo impressionante. Na verdade, eu estava pensando em como estender a funcionalidade de módulos de terceiros sem interferir com eles
Arthur Kovacs
5
Os decoradores realmente digitam todas as instâncias de um serviço ou têm o escopo definido apenas para o módulo que as decora? Em outras palavras, digamos que eu possua o módulo A que decora um serviço do módulo B. Então eu tenho o módulo C que depende do módulo A e do módulo B. Dentro do módulo C, o serviço do módulo B é a versão original ou decorada?
Jon Jaques
3
@ JonJaques - Essa é uma ótima pergunta. Eu não me deparei com essa situação. Se eu fosse adivinhar, a versão do serviço que o módulo C vê deveria ser a versão decorada do módulo A, mas não posso dizer isso com certeza até que eu mesmo tente. Por que você não escreve um simples plunkr / jsffidle e experimenta isso? Seria incrível se você pudesse compartilhar sua descoberta conosco. Felicidades.
tamakisquare
6
@ JonJaques - Não consegui segurar minha curiosidade, então adicionei algumas linhas ao meu exemplo original para encontrar a resposta para sua pergunta, link . Em suma, o palpite no meu comentário anterior está certo.
tamakisquare
17
Fábricas, serviços etc. são singletons (como são fornecidos), portanto, uma vez decorados, sempre decorados.
FlavourScape
66

Os decoradores nos permitem separar preocupações transversais e permitir que os serviços preservem o princípio de responsabilidade única sem se preocupar com o código de "infraestrutura".

Utilizações práticas de decoradores:

  • Armazenamento em cache: se tivermos um serviço que faz chamadas HTTP potencialmente caras, podemos envolvê-lo em um decorador de cache que verifica o armazenamento local antes de fazer a chamada externa.
  • Depuração / rastreamento: tenha um comutador, dependendo da configuração de desenvolvimento / produção, que decora seus serviços com invólucros de depuração ou rastreamento.
  • Limitação: limpe as chamadas acionadas com frequência em um wrapper de depuração. Permite interagir facilmente com serviços com tarifa limitada, por exemplo.

Em todos esses casos, limitamos o código no serviço à sua principal responsabilidade.

JBland
fonte
10

decoratorpode interceptar a instância de serviço criada por factory, service, value, providere oferece as opções para alterar algumas instance(service)que de outra forma não são configuráveis ​​/ com opções.

Também pode fornecer instâncias de simulação para fins de teste, por exemplo $http.

Daiwei
fonte
1
Vale a pena notar que você também pode substituir directivedefinições como apresentado por Ben Nadel
David Salamon
Aqui é a referência nos docs angular oficiais: https://docs.angularjs.org/guide/decorators
David Salamon
3

Em palavras simples, podemos dizer que é como um método de extensão. Para Ex. Nós temos uma classe e ela tem dois métodos. Em tempo de execução, queremos adicionar mais métodos a ela e usar o Decorator.

Não podemos usar $ allow.decorator com constantes porque não podemos alterar as constantes que elas estão elevando a propriedade somente leitura.

Gurupreet
fonte
1

Em suma, os decoradores podem ser descritos da seguinte forma: -

Uma função decoradora intercepta a criação de um serviço, permitindo substituir ou modificar o comportamento do serviço.

Utiliza o $provideserviço de forma angular e modifica ou substitui a implementação de outro serviço

$provide.decorator('service to decorate',['$delegate', function($delegate) {
  // $delegate - The original service instance, 
  //             which can be replaced, monkey patched, 
  //             configured, decorated or delegated to. 
  //             ie here what is there in the 'service to decorate'

  //   This function will be invoked, 
  //   when the service needs to be provided 
  //   and should return the decorated service instance.
  return $delegate;
}]);

Exemplo:

$provide.decorator('$log', ['$delegate', function($delegate) {
  // This will change implementation of log.war to log.error
  $delegate.warn = $delegate.error; 
  return $delegate;
}]);

Formulários

Além da resposta @JBland.

  • Configurações de localidade ampla do aplicativo: -

    Você pode encontrar um exemplo aqui

  • Alterando o comportamento padrão e a implementação existente de um serviço por serviço angular: -

    Você pode encontrar um exemplo aqui

  • Comutação de comportamento de uma função em diferentes ambientes.

samuelj90
fonte