Tropeça nessa frase ao ler sobre padrões de design.
Mas eu não entendo, alguém poderia explicar isso para mim?
oop
design-patterns
interface
software-design
ooad
never_had_a_name
fonte
fonte
Respostas:
Codificando contra meios de interface, o código do cliente sempre mantém um objeto de Interface que é fornecido por uma fábrica. Qualquer instância retornada pela fábrica seria do tipo Interface que qualquer classe candidata à fábrica deve ter implementado. Dessa forma, o programa cliente não está preocupado com a implementação e a assinatura da interface determina o que todas as operações podem ser feitas. Isso pode ser usado para alterar o comportamento de um programa em tempo de execução. Também ajuda a escrever programas muito melhores do ponto de vista da manutenção.
Aqui está um exemplo básico para você.
EDITAR
Atualizei o exemplo acima e adicionei uma
Speaker
classe base abstrata . Nesta atualização, adicionei um recurso a todos os alto-falantes no "SayHello". Todos os oradores falam "Olá Mundo". Portanto, esse é um recurso comum com função semelhante. Consulte o diagrama de classes e você encontrará essa interface deSpeaker
implementação de classe abstrataISpeaker
e marcaSpeak()
como abstrata, o que significa que cada implementação do Speaker é responsável por implementar oSpeak()
método, pois varia deSpeaker
paraSpeaker
. Mas todos os oradores dizem "Olá" por unanimidade. Portanto, na classe abstrata Speaker, definimos um método que diz "Hello World" e cadaSpeaker
implementação derivará oSayHello()
método.Considere um caso em
SpanishSpeaker
que não é possível dizer Olá, portanto, nesse caso, você pode substituir oSayHello()
método para quem fala espanhol e gerar uma exceção adequada.E podemos obter esse comportamento simplesmente adicionando uma classe abstrata base Speaker e algumas pequenas modificações em Cada implementação, deixando assim o programa original inalterado. Esse é um recurso desejado de qualquer aplicativo e facilita sua manutenção.
fonte
List
como o tipo, você ainda pode estar assumindo que o acesso aleatório é rápido chamando repetidamenteget(i)
.Pense em uma interface como um contrato entre um objeto e seus clientes. Essa é a interface especifica as coisas que um objeto pode fazer e as assinaturas para acessar essas coisas.
Implementações são os comportamentos reais. Digamos, por exemplo, que você tenha um método sort (). Você pode implementar o QuickSort ou MergeSort. Isso não deve importar a classificação de chamada de código do cliente, desde que a interface não seja alterada.
Bibliotecas como a API Java e o .NET Framework fazem uso pesado de interfaces, porque milhões de programadores usam os objetos fornecidos. Os criadores dessas bibliotecas precisam ter muito cuidado para não alterar a interface para as classes nessas bibliotecas, pois isso afetará todos os programadores que usam a biblioteca. Por outro lado, eles podem alterar a implementação o quanto quiserem.
Se, como programador, você codificar na implementação, assim que ela mudar, seu código deixará de funcionar. Então, pense nos benefícios da interface desta maneira:
fonte
Isso significa que você deve tentar escrever seu código para que ele use uma abstração (classe abstrata ou interface) em vez da implementação diretamente.
Normalmente, a implementação é injetada no seu código por meio do construtor ou de uma chamada de método. Portanto, seu código conhece a interface ou a classe abstrata e pode chamar qualquer coisa definida neste contrato. Como um objeto real (implementação da interface / classe abstrata) é usado, as chamadas estão operando no objeto.
Este é um subconjunto do
Liskov Substitution Principle
(LSP), o L dosSOLID
princípios.Um exemplo no .NET seria codificar em
IList
vez deList
ouDictionary
, para que você pudesse usar qualquer classe que implemente de formaIList
intercambiável no seu código:Outro exemplo da BCL (Base Class Library) é a
ProviderBase
classe abstrata - isso fornece alguma infraestrutura e, o que é mais importante, significa que todas as implementações de provedor podem ser usadas de forma intercambiável se você codificar contra ela.fonte
Se você escrever uma classe de carro na era de carros de combustão, há uma grande chance de implementar o oilChange () como parte dessa classe. Mas, quando carros elétricos são introduzidos, você estaria com problemas, pois não há troca de óleo envolvida nesses carros e nenhuma implementação.
A solução para o problema é ter uma interface performMaintenance () na classe Car e ocultar detalhes dentro da implementação apropriada. Cada tipo de carro forneceria sua própria implementação para performMaintenance (). Como proprietário de um carro, tudo com o qual você precisa lidar é performMaintenance () e não se preocupa em se adaptar quando houver uma MUDANÇA.
Explicação adicional: você é proprietário de um carro e possui vários carros. Você cria o serviço que deseja terceirizar. No nosso caso, queremos terceirizar o trabalho de manutenção de todos os carros.
Você não quer se preocupar em associar o tipo de carro ao provedor de serviços. Você apenas especifica quando deseja agendar a manutenção e invocá-la. Uma empresa de serviços apropriada deve entrar e executar o trabalho de manutenção.
Abordagem alternativa.
Você invoca o trabalho e faz você mesmo. Aqui você fará o trabalho de manutenção apropriado.
Qual é a desvantagem da segunda abordagem? Você pode não ser o especialista em encontrar a melhor maneira de fazer a manutenção. Seu trabalho é dirigir o carro e se divertir. Não estar no negócio de mantê-lo.
Qual é a desvantagem da primeira abordagem? Existe a sobrecarga de encontrar uma empresa etc. A menos que você seja uma empresa de aluguel de carros, pode não valer a pena.
fonte
Esta afirmação é sobre acoplamento. Um motivo potencial para o uso de programação orientada a objetos é a reutilização. Portanto, por exemplo, você pode dividir seu algoritmo entre dois objetos colaboradores A e B. Isso pode ser útil para a criação posterior de outro algoritmo, que pode reutilizar um ou outro dos dois objetos. No entanto, quando esses objetos se comunicam (enviam mensagens - chamam métodos), eles criam dependências entre si. Mas se você quiser usar um sem o outro, precisará especificar o que outro objeto C deve fazer para o objeto A, se substituirmos B. Essas descrições são chamadas de interfaces. Isso permite que o objeto A se comunique sem alterações com objetos diferentes que dependem da interface. A declaração que você mencionou diz que, se você planeja reutilizar parte de um algoritmo (ou mais geralmente um programa), deve criar interfaces e confiar nelas,
fonte
Como já foi dito, isso significa que seu código de chamada deve conhecer apenas um pai abstrato, NÃO a classe de implementação real que fará o trabalho.
O que ajuda a entender isso é o PORQUE você deve sempre programar em uma interface. Há muitas razões, mas duas das mais fáceis de explicar são
1) Teste.
Digamos que eu tenho todo o código do banco de dados em uma classe. Se meu programa souber sobre a classe concreta, só posso testar meu código executando-o realmente nessa classe. Estou usando -> para significar "fala com".
WorkerClass -> DALClass No entanto, vamos adicionar uma interface ao mix.
WorkerClass -> IDAL -> DALClass.
Portanto, o DALClass implementa a interface IDAL, e a classe Worker apenas chama através disso.
Agora, se quisermos escrever testes para o código, poderíamos criar uma classe simples que funciona como um banco de dados.
WorkerClass -> IDAL -> IFakeDAL.
2) Reutilização
Seguindo o exemplo acima, digamos que queremos passar do SQL Server (que nosso DALClass concreto usa) para o MonogoDB. Isso exigiria muito trabalho, mas NÃO se programamos para uma interface. Nesse caso, apenas escrevemos a nova classe de banco de dados e alteramos (via fábrica)
WorkerClass -> IDAL -> DALClass
para
WorkerClass -> IDAL -> MongoDBClass
fonte
interfaces descrevem recursos. ao escrever um código imperativo, fale sobre os recursos que você está usando, em vez de tipos ou classes específicos.
fonte