oop - pattern - java ioc




O que é inversão de controle? (20)

  1. Inversão de controle é um padrão usado para desacoplar componentes e camadas no sistema. O padrão é implementado através da injeção de dependências em um componente quando ele é construído. Essas dependências geralmente são fornecidas como interfaces para dissociação adicional e para suportar a testabilidade. Os contêineres IoC / DI, como Castle Windsor, Unity, são ferramentas (bibliotecas) que podem ser usadas para fornecer IoC. Essas ferramentas fornecem recursos estendidos acima e além do simples gerenciamento de dependências, incluindo vida útil, AOP / interceptação, política etc.

  2. uma. Evita que um componente seja responsável por gerenciar suas dependências.
    b. Fornece a capacidade de trocar implementações de dependência em diferentes ambientes.
    c. Permite que um componente seja testado através da simulação de dependências.
    d. Fornece um mecanismo para compartilhar recursos em um aplicativo.

  3. uma. Crítico ao fazer desenvolvimento orientado a teste. Sem a IoC, pode ser difícil testar, porque os componentes em teste são altamente acoplados ao restante do sistema.
    b. Crítico ao desenvolver sistemas modulares. Um sistema modular é um sistema cujos componentes podem ser substituídos sem a necessidade de recompilação.
    c. Crítico se houver muitas preocupações transversais que precisam ser abordadas, compartilhadas em um aplicativo corporativo.

Inversão de controle (ou IoC) pode ser bastante confusa quando é encontrada pela primeira vez.

  1. O que é isso?
  2. Qual problema ele resolve?
  3. Quando é apropriado usar e quando não?

  1. Artigo da Wikipedia . Para mim, a inversão de controle está transformando seu código gravado seqüencialmente e transformando-o em uma estrutura de delegação. Em vez de seu programa controlar explicitamente tudo, ele cria uma classe ou biblioteca com determinadas funções a serem chamadas quando certas coisas acontecem.

  2. Resolve a duplicação de código. Por exemplo, antigamente, você escrevia manualmente seu próprio loop de eventos, pesquisando as bibliotecas do sistema para novos eventos. Hoje em dia, nas APIs mais modernas, você simplesmente diz às bibliotecas do sistema em quais eventos você está interessado, e ele será informado quando eles acontecerem.

  3. A inversão de controle é uma maneira prática de reduzir a duplicação de código e, se você copiar um método inteiro e alterar apenas um pequeno pedaço do código, considere enfrentá-lo com inversão de controle. A inversão do controle é facilitada em muitos idiomas através do conceito de delegados, interfaces ou até mesmo ponteiros de funções brutas.

    Não é apropriado usar em todos os casos, porque o fluxo de um programa pode ser mais difícil de seguir quando escrito dessa maneira. É uma maneira útil de projetar métodos ao escrever uma biblioteca que será reutilizada, mas deve ser usada com moderação no núcleo do seu próprio programa, a menos que realmente resolva um problema de duplicação de código.


Antes de usar a Inversão de controle, você deve estar ciente do fato de que ela tem seus prós e contras e, por isso, deve saber por que usá-la.

Prós:

  • Seu código é dissociado para que você possa trocar facilmente implementações de uma interface com implementações alternativas
  • É um forte motivador para codificar contra interfaces em vez de implementações
  • É muito fácil escrever testes de unidade para o seu código, porque ele depende apenas dos objetos que ele aceita em seus construtores / setters e você pode inicializá-los facilmente com os objetos certos isoladamente.

Contras:

  • O IoC não apenas inverte o fluxo de controle em seu programa, como também o obscurece consideravelmente. Isso significa que você não pode mais apenas ler seu código e pular de um lugar para outro, porque as conexões que normalmente estariam no seu código não estão mais no código. Em vez disso, está nos arquivos de configuração XML ou nas anotações e no código do seu contêiner de IoC que interpreta esses metadados.
  • Surge uma nova classe de erros em que você configura incorretamente sua configuração XML ou suas anotações e pode gastar muito tempo descobrindo por que seu contêiner IoC injeta uma referência nula em um de seus objetos sob determinadas condições.

Pessoalmente, vejo os pontos fortes da IoC e realmente gosto deles, mas tendem a evitá-la sempre que possível, porque transforma seu software em uma coleção de classes que não constituem mais um programa "real", mas apenas algo que precisa ser reunido por Os metadados de configuração ou anotação XML e desmoronariam (e desmoronariam) sem ele.


Eu concordo com o NilObject , mas gostaria de acrescentar a isso:

se você estiver copiando um método inteiro e alterando apenas um pequeno pedaço do código, considere enfrentá-lo com inversão de controle

Se você está copiando e colando códigos, quase sempre está fazendo algo errado. Codificado como o princípio do design Uma vez e Apenas uma vez .


Inversão de controle (ou IoC) é sobre obter liberdade (você se casa, você perdeu a liberdade e está sendo controlado. Você se divorciou, acabou de implementar a Inversão de controle. Era isso que chamamos de "desacoplado". Bom sistema de computador desencoraja um relacionamento muito próximo.) mais flexibilidade (a cozinha do seu escritório serve apenas água da torneira, que é a sua única opção quando você deseja beber. Seu chefe implementou a Inversão de Controle instalando uma nova máquina de café. Agora você obtém o flexibilidade de escolher água da torneira ou café.) e menos dependência (seu parceiro tem um emprego, você não tem um emprego, depende financeiramente do seu parceiro, portanto, é controlado. Você encontra um emprego, implementou a Inversão de Controle. Um bom sistema de computador incentiva a dependência.)

Ao usar um computador de mesa, você escrava (ou diz, controla). Você tem que sentar diante de uma tela e olhar para ela. Usando o teclado para digitar e usando o mouse para navegar. E um software mal escrito pode escravizar você ainda mais. Se você substituir sua área de trabalho por um laptop, terá um controle um pouco invertido. Você pode facilmente pegá-lo e se movimentar. Então agora você pode controlar onde está com seu computador, em vez de controlá-lo.

Ao implementar a Inversão de controle, um consumidor de software / objeto obtém mais controles / opções sobre o software / objetos, em vez de ser controlado ou ter menos opções.

Com as idéias acima em mente. Ainda sentimos falta de uma parte essencial da IoC. No cenário de IoC, o consumidor de software / objeto é uma estrutura sofisticada. Isso significa que o código que você criou não é chamado por você. Agora vamos explicar por que dessa maneira funciona melhor para um aplicativo da web.

Suponha que seu código seja um grupo de trabalhadores. Eles precisam construir um carro. Esses trabalhadores precisam de um local e ferramentas (uma estrutura de software) para construir o carro. Uma estrutura de software tradicional será como uma garagem com muitas ferramentas. Portanto, os trabalhadores precisam fazer um plano e usar as ferramentas para construir o carro. Construir um carro não é um negócio fácil, será muito difícil para os trabalhadores planejar e cooperar adequadamente. Uma estrutura de software moderna será como uma fábrica de carros moderna, com todas as instalações e gerentes instalados. Os trabalhadores não precisam fazer nenhum plano, os gerentes (parte da estrutura, eles são as pessoas mais inteligentes e o plano mais sofisticado) ajudarão a coordenar para que os trabalhadores saibam quando fazer seu trabalho (a estrutura chama seu código). Os funcionários só precisam ser flexíveis o suficiente para usar as ferramentas que os gerentes lhes fornecem (usando a Injeção de Dependência).

Embora os trabalhadores dêem o controle do gerenciamento do projeto no nível superior aos gerentes (a estrutura). Mas é bom ter alguns profissionais ajudando. Este é o conceito de IoC realmente provém.

Os aplicativos modernos da Web com uma arquitetura MVC dependem da estrutura para fazer o roteamento de URL e colocar os controladores no lugar para a estrutura chamar.

Injeção de Dependência e Inversão de Controle estão relacionadas. A injeção de dependência está no nível micro e a inversão de controle está no nível macro . Você deve comer todas as mordidas (implementar DI) para terminar uma refeição (implementar IoC).


Inversão de controles é sobre separar preocupações.

Sem IoC : você possui um laptop e acidentalmente interrompe a tela. E, caramba, você encontra o mesmo modelo de tela do laptop em nenhum lugar do mercado. Então você está preso.

Com o IoC : você tem um computador desktop e acidentalmente interrompe a tela. Você descobre que pode pegar praticamente qualquer monitor de mesa do mercado e funciona bem com sua área de trabalho.

Sua área de trabalho implementa com êxito a IoC neste caso. Ele aceita vários tipos de monitores, enquanto o laptop não, ele precisa de uma tela específica para ser consertada.


Mas acho que você precisa ter muito cuidado com isso. Se você usar demais esse padrão, criará um design muito complicado e um código ainda mais complicado.

Como neste exemplo com o TextEditor: se você tiver apenas um SpellChecker, talvez não seja realmente necessário usar a IoC? A menos que você precise escrever testes de unidade ou algo assim ...

De qualquer forma: seja razoável. Padrão de design são boas práticas, mas não a Bíblia a ser pregada. Não cole em todos os lugares.


O que é inversão de controle?

Se você seguir estas duas etapas simples, terá feito inversão de controle:

  1. Separe a parte do que fazer e da parte em que fazer.
  2. Assegure-se de que quando a parte souber o mínimo possível sobre qual parte; e vice versa.

Existem várias técnicas possíveis para cada uma dessas etapas com base na tecnologia / idioma que você está usando para sua implementação.

-

A parte de inversão da Inversão de Controle (IoC) é uma coisa confusa; porque inversão é o termo relativo. A melhor maneira de entender a IoC é esquecer essa palavra!

-

Exemplos

  • Manipulação de eventos. Manipuladores de eventos (parte do que fazer) - Gerando eventos (parte do que fazer)
  • Interfaces. Cliente do componente (parte quando fazer) - Implementação da interface do componente (parte que fazer)
  • xUnit. Configuração e TearDown (parte do que fazer) - as estruturas do xUnit chamam a Instalação no início e TearDown no final (parte da tarefa)
  • Modelo método padrão de design. método de modelo parte do que fazer - implementação primitiva da subclasse parte do que fazer
  • Métodos de contêiner DLL em COM. DllMain, DllCanUnload, etc (parte do que fazer) - COM / OS (parte do que fazer)

Parece que a coisa mais confusa em "IoC", o acrônimo e o nome pelo qual ele representa, é que é um nome muito glamouroso - quase um nome barulhento.

Nós realmente precisamos de um nome para descrever a diferença entre programação procedural e orientada a eventos? OK, se precisarmos, mas precisamos escolher um novo nome "maior que a vida" que confunda mais do que resolve?


Por exemplo, a tarefa nº 1 é criar um objeto. Sem o conceito de COI, a tarefa 1 deve ser executada pelo programador, mas com o conceito de COI, a tarefa 1 será feita por contêiner.

Em resumo, o controle é invertido do programador para o contêiner. Então, isso é chamado de inversão de controle.

Encontrei um bom exemplo here .


Suponha que você seja um objeto. E você vai a um restaurante:

Sem IoC : você pede "maçã" e sempre recebe maçã quando pede mais.

Com o IoC : você pode pedir "fruta". Você pode obter frutas diferentes cada vez que for servido. por exemplo, maçã, laranja ou melancia.

Portanto, obviamente, a IoC é preferida quando você gosta das variedades.


Vamos dizer que fazemos algumas reuniões em algum hotel.

Muitas pessoas, muitas garrafas de água, muitos copos de plástico.

Quando alguém quer beber, ela enche a xícara, bebe e joga a xícara no chão.

Depois de uma hora ou algo assim, temos um piso coberto de copos de plástico e água.

Deixe o controle invertido.

A mesma reunião no mesmo lugar, mas em vez de copos de plástico, temos um garçom com um copo de vidro (Singleton)

e ela sempre oferece aos convidados que bebem.

Quando alguém quer beber, ela pega o copo de garçom, bebe e devolve ao garçom.

Deixando de lado a questão da última forma higiênica de controle do processo de beber é muito mais eficaz e econômica.

E é exatamente isso que o Spring (outro contêiner de IoC, por exemplo: Guice) faz. Em vez de permitir que o aplicativo crie o que é necessário usando a nova palavra-chave (copo de plástico), o contêiner Spring IoC oferece a todo momento a aplicação da mesma instância (singleton) do objeto necessário (copo de água).

Pense em si mesmo como organizador dessa reunião. Você precisa enviar uma mensagem para a administração do hotel que

os membros da reunião precisarão de um copo de água, mas não de um pedaço de bolo.

Exemplo:-

public class MeetingMember {

    private GlassOfWater glassOfWater;

    ...

    public void setGlassOfWater(GlassOfWater glassOfWater){
        this.glassOfWater = glassOfWater;
    }
    //your glassOfWater object initialized and ready to use...
    //spring IoC  called setGlassOfWater method itself in order to
    //offer to meetingMember glassOfWater instance

}

Links Úteis:-


Eu li muitas respostas para isso, mas se alguém ainda está confuso e precisa de um termo "ultra-leigo" para explicar a IoC, aqui está minha opinião:

Imagine pais e filhos conversando entre si.

Sem IoC:

* Pai : Você só pode falar quando eu fizer perguntas e você só pode agir quando eu der permissão.

Pai : Isso significa que você não pode me perguntar se pode comer, brincar, ir ao banheiro ou até dormir se eu não perguntar.

Pai : Você quer comer?

Criança : Não.

Pai : Ok, eu volto. Espere por mim.

Criança : (Quer brincar, mas como não há perguntas dos pais, a criança não pode fazer nada).

Depois de 1 hora...

Pai : estou de volta. Você quer jogar?

Criança : Sim.

Pai : Permissão concedida.

Criança : (finalmente é capaz de brincar).

Este cenário simples explica que o controle está centralizado no pai. A liberdade da criança é restrita e depende muito da pergunta dos pais. A criança SOMENTE pode falar quando for solicitada a falar e SOMENTE pode agir quando tiver permissão.

Com IoC:

A criança agora tem a capacidade de fazer perguntas e os pais podem responder com respostas e permissões. Simplesmente significa que o controle está invertido! A criança agora está livre para fazer perguntas a qualquer momento e, embora ainda exista dependência dos pais em relação às permissões, ela não depende dos meios de falar / fazer perguntas.

De uma maneira tecnológica de explicar, isso é muito semelhante à interação console / shell / cmd x GUI. (Qual é a resposta de Mark Harrison acima da resposta superior no.2). No console, você depende do que está sendo solicitado / exibido e não pode pular para outros menus e recursos sem responder à pergunta primeiro; seguindo um fluxo seqüencial estrito. (programaticamente, isso é como um loop de método / função). No entanto, com a GUI, os menus e os recursos são definidos e o usuário pode selecionar o que for necessário, tendo mais controle e menos restrições. (programaticamente, os menus têm retorno de chamada quando selecionados e uma ação ocorre).


Inversão de controle é quando você vai ao supermercado e sua esposa fornece a lista de produtos para compra.

Em termos de programação, ela passou uma função de retorno de chamada getProductList()para a função que você está executando - doShopping().

Ele permite que o usuário da função defina algumas partes dela, tornando-a mais flexível.


Inversion of Control is a generic principle, while Dependency Injection realises this principle as a design pattern for object graph construction (ie configuration controls how the objects are referencing each other, rather than the object itself controlling how to get the reference to another object).

Olhando Inversão do Controle como um padrão de design, precisamos olhar para o que estamos invertendo. A injeção de dependência inverte o controle da construção de um gráfico de objetos. Se contada no termo do leigo, a inversão de controle implica mudança no fluxo de controle no programa. Por exemplo. No aplicativo autônomo tradicional, temos o método principal, de onde o controle é passado para outras bibliotecas de terceiros (no caso, usamos a função de biblioteca de terceiros), mas através da inversão do controle de controle é transferido do código da biblioteca de terceiros para o nosso código , como estamos recebendo o serviço de uma biblioteca de terceiros. Mas há outros aspectos que precisam ser invertidos dentro de um programa - por exemplo, invocação de métodos e threads para executar o código.

Para os interessados ​​em mais detalhes sobre a Inversão de controle, foi publicado um artigo descrevendo uma imagem mais completa da Inversão de controle como padrão de design (OfficeFloor: usando padrões de escritório para melhorar o design de software http://doi.acm.org/10.1145/2739011.2739013 com uma cópia gratuita disponível para download em http://www.officefloor.net/about.html ).

O que é identificado é o seguinte relacionamento:

Inversão de controle (para métodos) = Injeção de dependência (estado) + Injeção de continuação + Injeção de rosca

Resumo do relacionamento acima para Inversão de controle disponível - http://dzone.com/articles/inversion-of-coupling-control


IoC trata-se de inverter o relacionamento entre seu código e o código de terceiros (biblioteca / estrutura):

  • No desenvolvimento s / w normal, você escreve o método main () e chama os métodos "library". Você está no controle :)
  • Na IoC, o "framework" controla main () e chama seus métodos. O Framework está no controle :(

DI (Injection Dependency) é sobre como o controle flui no aplicativo. O aplicativo de desktop tradicional tinha fluxo de controle do seu aplicativo (método main ()) para outras chamadas de método de biblioteca, mas com o fluxo de controle de DI invertido, a estrutura cuida de iniciar seu aplicativo, inicializando-o e invocando seus métodos sempre que necessário.

No final, você sempre vence :)


Criar um objeto dentro da classe é chamado de acoplamento rígido, o Spring remove essa dependência seguindo um padrão de design (DI / IOC). Em qual objeto da classe passou no construtor em vez de criar na classe. Além disso, damos uma variável de referência de superclasse no construtor para definir uma estrutura mais geral.


Encontrei um exemplo muito claro here que explica como o 'controle é invertido'.

Código clássico (sem injeção de dependência)

Aqui está como um código que não usa DI funcionará aproximadamente:

  • A aplicação precisa de Foo (por exemplo, um controlador), portanto:
  • Aplicativo cria Foo
  • Aplicativo chama Foo
    • Foo precisa de Bar (por exemplo, um serviço), então:
    • Foo cria Bar
    • Foo chama Bar
      • Bar precisa do Bim (um serviço, um repositório,…), então:
      • Bar cria Bim
      • Bar faz alguma coisa

Usando injeção de dependência

Aqui está como um código usando DI funcionará aproximadamente:

  • O aplicativo precisa de Foo, que precisa de Bar, que precisa de Bim, então:
  • Aplicativo cria Bim
  • Aplicativo cria Bar e fornece Bim
  • Aplicativo cria Foo e fornece barra
  • Aplicativo chama Foo
    • Foo chama Bar
      • Bar faz alguma coisa

O controle das dependências é invertido de um chamado para o chamado.

Que problemas ele resolve?

A injeção de dependência facilita a troca com a implementação diferente das classes injetadas. Durante o teste de unidade, você pode injetar uma implementação fictícia, o que facilita muito o teste.

Ex: suponha que seu aplicativo armazene o arquivo enviado pelo usuário no Google Drive, com o DI, o código do seu controlador pode ficar assim:

class SomeController
{
    private $storage;

    function __construct(StorageServiceInterface $storage)
    {
        $this->storage = $storage;
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

class GoogleDriveService implements StorageServiceInterface
{
    public function authenticate($user) {}
    public function putFile($file) {}
    public function getFile($file) {}
}

Quando seus requisitos mudam, digamos, em vez do GoogleDrive, você é solicitado a usar o Dropbox. Você só precisa escrever uma implementação de caixa de depósito para o StorageServiceInterface. Você não faz nenhuma alteração no controlador desde que a implementação do Dropbox adira ao StorageServiceInterface.

Durante o teste, você pode criar a simulação para o StorageServiceInterface com a implementação fictícia em que todos os métodos retornam nulos (ou qualquer valor predefinido conforme o requisito de teste).

Em vez disso, se você tivesse a classe controller para construir o objeto de armazenamento com a newpalavra - chave desta forma:

class SomeController
{
    private $storage;

    function __construct()
    {
        $this->storage = new GoogleDriveService();
    }

    public function myFunction () 
    {
        return $this->storage->getFile($fileName);
    }
}

Quando você quiser alterar a implementação do Dropbox, substitua todas as linhas em que o newobjeto GoogleDriveService é construído e use o DropboxService. Além disso, ao testar a classe SomeController, o construtor sempre espera a classe GoogleDriveService e os métodos reais dessa classe são acionados.

Quando é apropriado e quando não? Na minha opinião, você usa DI quando pensa que há (ou pode haver) implementações alternativas de uma classe.


Eu gosto desta explicação: http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/

Começa simples e mostra exemplos de código também.

O consumidor, X, precisa da classe consumida, Y, para realizar alguma coisa. Tudo isso é bom e natural, mas X realmente precisa saber que usa Y?

Não basta que X saiba que usa algo que possui o comportamento, os métodos, as propriedades etc. de Y sem saber quem realmente implementa o comportamento?

Ao extrair uma definição abstrata do comportamento usado por X em Y, ilustrado como abaixo, e permitir que o consumidor X use uma instância disso em vez de Y, ele pode continuar fazendo o que faz sem precisar conhecer as especificidades sobre Y.

Na ilustração acima, Y implementa I e X usa uma instância de I. Embora seja bem possível que X ainda use Y, o interessante é que X não sabe disso. Só sabe que usa algo que implementa I.

Leia o artigo para obter mais informações e descrição de benefícios, como:

  • X não depende mais de Y
  • Mais flexível, a implementação pode ser decidida em tempo de execução
  • Isolamento da unidade de código, teste mais fácil

...


Inversão de controle é sobre a transferência de controle da biblioteca para o cliente. Faz mais sentido quando falamos de um cliente que injeta (passa) um valor de função (expressão lambda) em uma função de ordem superior (função de biblioteca) que controla (altera) o comportamento da função de biblioteca. Um cliente ou estrutura que injeta dependências de bibliotecas (que carregam comportamento) nas bibliotecas também pode ser considerado IoC







inversion-of-control