On tombe sur cette phrase en lisant sur les modèles de conception.
Mais je ne comprends pas, quelqu'un pourrait-il m'expliquer cela?
oop
design-patterns
interface
software-design
ooad
never_had_a_name
la source
la source
Réponses:
Codage par rapport aux moyens d'interface, le code client contient toujours un objet Interface qui est fourni par une usine. Toute instance retournée par l'usine serait de type Interface que toute classe candidate d'usine doit avoir implémentée. De cette façon, le programme client ne se soucie pas de l'implémentation et la signature de l'interface détermine ce que toutes les opérations peuvent être effectuées. Cela peut être utilisé pour modifier le comportement d'un programme au moment de l'exécution. Il vous aide également à écrire de bien meilleurs programmes du point de vue de la maintenance.
Voici un exemple de base pour vous.
ÉDITER
J'ai mis à jour l'exemple ci-dessus et ajouté une
Speaker
classe de base abstraite . Dans cette mise à jour, j'ai ajouté une fonctionnalité à tous les haut-parleurs pour "SayHello". Tous les orateurs parlent "Hello World". C'est donc une caractéristique commune avec une fonction similaire. Reportez-vous au diagramme de classes et vous constaterez queSpeaker
la classe abstraite implémente l'ISpeaker
interface et marque leSpeak()
comme abstrait, ce qui signifie que chaque implémentation Speaker est responsable de l'implémentation de laSpeak()
méthode car elle varie deSpeaker
àSpeaker
. Mais tous les orateurs disent "Bonjour" à l'unanimité. Ainsi, dans la classe abstraite Speaker, nous définissons une méthode qui dit "Hello World" et chaqueSpeaker
implémentation dérivera laSayHello()
méthode.Prenons un cas où
SpanishSpeaker
je ne peux pas dire bonjour, alors dans ce cas, vous pouvez remplacer laSayHello()
méthode pour Spanish Speaker et lever une exception appropriée.Et nous pourrions obtenir ce comportement en ajoutant simplement une classe abstraite de base Speaker et quelques modifications mineures dans chaque implémentation, laissant ainsi le programme d'origine inchangé. Il s'agit d'une fonctionnalité souhaitée de toute application et elle rend votre application facilement maintenable.
la source
List
comme type, vous pouvez toujours supposer que l'accès aléatoire est rapide en appelant à plusieurs reprisesget(i)
.Pensez à une interface comme un contrat entre un objet et ses clients. C'est l'interface spécifie les choses qu'un objet peut faire, et les signatures pour accéder à ces choses.
Les implémentations sont les comportements réels. Disons par exemple que vous avez une méthode sort (). Vous pouvez implémenter QuickSort ou MergeSort. Cela ne devrait pas avoir d'importance pour le code client appelant sort tant que l'interface ne change pas.
Les bibliothèques comme l'API Java et le .NET Framework font un usage intensif des interfaces car des millions de programmeurs utilisent les objets fournis. Les créateurs de ces bibliothèques doivent faire très attention à ne pas changer l'interface avec les classes de ces bibliothèques car cela affectera tous les programmeurs utilisant la bibliothèque. D'un autre côté, ils peuvent changer la mise en œuvre autant qu'ils le souhaitent.
Si, en tant que programmeur, vous codez par rapport à l'implémentation, dès qu'elle change, votre code cesse de fonctionner. Pensez donc aux avantages de l'interface de cette façon:
la source
Cela signifie que vous devez essayer d'écrire votre code pour qu'il utilise une abstraction (classe abstraite ou interface) au lieu de l'implémentation directement.
Normalement, l'implémentation est injectée dans votre code via le constructeur ou un appel de méthode. Ainsi, votre code connaît l'interface ou la classe abstraite et peut appeler tout ce qui est défini sur ce contrat. Lorsqu'un objet réel (implémentation de l'interface / classe abstraite) est utilisé, les appels opèrent sur l'objet.
Il s'agit d'un sous-ensemble du
Liskov Substitution Principle
(LSP), le L desSOLID
principes.Un exemple dans .NET serait de coder avec
IList
au lieu deList
ouDictionary
, vous pouvez donc utiliser n'importe quelle classe qui implémente deIList
manière interchangeable dans votre code:Un autre exemple de la bibliothèque de classes de base (BCL) est la
ProviderBase
classe abstraite - cela fournit une certaine infrastructure et, ce qui est important, signifie que toutes les implémentations de fournisseur peuvent être utilisées de manière interchangeable si vous codez contre elle.la source
Si vous deviez écrire une classe de voiture à l'époque des voitures à combustion, il y a de fortes chances que vous implémentiez oilChange () dans le cadre de cette classe. Mais, lorsque les voitures électriques sont introduites, vous seriez en difficulté car il n'y a pas de changement d'huile pour ces voitures et aucune mise en œuvre.
La solution au problème est d'avoir une interface performMaintenance () dans la classe Car et de cacher les détails dans une implémentation appropriée. Chaque type de voiture fournirait sa propre implémentation pour performMaintenance (). En tant que propriétaire d'une voiture, tout ce que vous avez à faire est de performMaintenance () et de ne pas vous soucier de vous adapter en cas de CHANGEMENT.
Explication supplémentaire: vous êtes un propriétaire de voiture qui possède plusieurs voitures. Vous découpez le service que vous souhaitez externaliser. Dans notre cas, nous voulons externaliser les travaux de maintenance de toutes les voitures.
Vous ne voulez pas vous soucier d'associer le type de voiture au fournisseur de services. Vous spécifiez simplement quand vous souhaitez planifier la maintenance et l'appeler. Une société de service appropriée doit intervenir et effectuer les travaux de maintenance.
Approche alternative.
Vous invoquez le travail et le faites vous-même. Ici, vous allez effectuer le travail de maintenance approprié.
Quel est l'inconvénient de la 2ème approche? Vous n'êtes peut-être pas l'expert pour trouver la meilleure façon d'effectuer la maintenance. Votre travail consiste à conduire la voiture et à en profiter. Ne pas avoir à le maintenir.
Quel est l'inconvénient de la première approche? Il y a des frais généraux liés à la recherche d'une entreprise, etc.
la source
Cette déclaration concerne le couplage. Une des raisons potentielles de l'utilisation de la programmation orientée objet est la réutilisation. Ainsi, par exemple, vous pouvez diviser votre algorithme entre deux objets collaboratifs A et B. Cela peut être utile pour la création ultérieure d'un autre algorithme, qui pourrait réutiliser l'un ou l'autre des deux objets. Cependant, lorsque ces objets communiquent (envoient des messages - méthodes d'appel), ils créent des dépendances entre eux. Mais si vous voulez utiliser l'un sans l'autre, vous devez spécifier ce que doit faire un autre objet C pour l'objet A si nous remplaçons B. Ces descriptions sont appelées interfaces. Cela permet à l'objet A de communiquer sans changement avec un objet différent en fonction de l'interface. La déclaration que vous avez mentionnée dit que si vous prévoyez de réutiliser une partie d'un algorithme (ou plus généralement d'un programme), vous devez créer des interfaces et vous en remettre,
la source
Comme d'autres l'ont dit, cela signifie que votre code appelant ne devrait connaître qu'un parent abstrait, PAS la classe d'implémentation réelle qui fera le travail.
Ce qui aide à comprendre ceci est le POURQUOI vous devez toujours programmer une interface. Il y a de nombreuses raisons, mais deux des plus faciles à expliquer sont
1) Test.
Disons que j'ai tout mon code de base de données dans une classe. Si mon programme connaît la classe concrète, je ne peux tester mon code qu'en l'exécutant réellement sur cette classe. J'utilise -> pour signifier "parle à".
WorkerClass -> DALClass Cependant, ajoutons une interface au mix.
WorkerClass -> IDAL -> DALClass.
Ainsi, DALClass implémente l'interface IDAL, et la classe de travail appelle UNIQUEMENT à travers cela.
Maintenant, si nous voulons écrire des tests pour le code, nous pourrions plutôt créer une classe simple qui agit simplement comme une base de données.
WorkerClass -> IDAL -> IFakeDAL.
2) Réutiliser
En suivant l'exemple ci-dessus, disons que nous voulons passer de SQL Server (que notre DALClass concrète utilise) à MonogoDB. Cela demanderait un travail majeur, mais PAS si nous avons programmé une interface. Dans ce cas, nous écrivons simplement la nouvelle classe DB et changeons (via l'usine)
WorkerClass -> IDAL -> DALClass
à
WorkerClass -> IDAL -> MongoDBClass
la source
les interfaces décrivent les capacités. lors de l'écriture de code impératif, parlez des capacités que vous utilisez, plutôt que des types ou classes spécifiques.
la source