Maison  >  Article  >  Java  >  Tous les architectes Java connaissent-ils ces 6 principes de conception ? Doit maîtriser

Tous les architectes Java connaissent-ils ces 6 principes de conception ? Doit maîtriser

php是最好的语言
php是最好的语言original
2018-08-01 16:23:141600parcourir

Dans notre développement quotidien, nous devons souvent suivre certains principes et modèles. Ceux-ci sont en fait résumés par nos prédécesseurs en développement. Quel que soit le développement logiciel que nous effectuons, il nous sera bénéfique et inoffensif, et nous le maîtrisons. .Ces principes et techniques ne feront que vous aider à améliorer votre efficacité.Cet article résume ces principes et explique leur signification, vous donnant une valeur de référence.J'espère que cet article pourra vous inspirer et vous aider à mieux apprendre les connaissances Java. apache php mysql

commencez !

Principes de développement

Les principes de base (solides) de l'orientation objet sont au nombre de cinq, mais en plus de ceux-ci sont ceux-là qui sont souvent mentionnés En plus des cinq, il y a la loi de Déméter et le principe de synthèse et de réutilisation, etc., donc dans les articles courants, il y a six ou sept principes en plus, je donnerai également quelques autres livres et informations connexes ; sur Internet Principes émergents ;

S SRP à responsabilité unique

Principe de responsabilité unique, une classe, il est préférable de n'en faire qu'une seule. chose, une seule fait en sorte qu'elle change. Le principe de responsabilité unique peut être considéré comme une extension du principe orienté objet de faible couplage et de forte cohésion. La responsabilité est définie comme la cause du changement pour améliorer la cohésion et réduire la cause du changement.

Définition

Un objet ne doit contenir qu'une seule responsabilité, et la responsabilité doit être complètement encapsulée dans une classe. (Chaque objet doit avoir une seule responsabilité, et cette responsabilité doit être entièrement encapsulée par la classe.), c'est-à-dire qu'il est également défini qu'il existe une et une seule raison pour laquelle la classe change. Cliquez ici pour consulter des explications détaillées sur 9 solutions pour la conception d'architectures à haute disponibilité.

Analyse des principes

  • Plus une classe (ou aussi grande qu'un module ou aussi petite qu'une méthode) assume de responsabilités, moins elle a de chances d'être réutilisée, et si Si une classe assume trop de responsabilités, cela équivaut à coupler ces responsabilités. Lorsqu'une des responsabilités change, cela peut affecter le fonctionnement des autres responsabilités.

  • Les responsabilités d'une classe comprennent principalement deux aspects : les responsabilités en matière de données et les responsabilités comportementales se reflètent à travers ses attributs, tandis que les responsabilités comportementales se reflètent à travers ses méthodes.

  • Le principe de responsabilité unique est une ligne directrice pour atteindre une cohésion élevée et un faible couplage. On le retrouve dans de nombreuses techniques de refactorisation de code. C'est le principe le plus simple mais le plus difficile à appliquer. exige que les concepteurs découvrent les différentes responsabilités d'une classe et les séparent, et la découverte des multiples responsabilités d'une classe nécessite que les concepteurs aient de solides capacités d'analyse et de conception et une expérience de refactorisation pertinente.

Avantages

  • Réduisez la complexité de la classe et les responsabilités de la classe sont claires et claires. Par exemple, les responsabilités en matière de données et les responsabilités comportementales sont claires et claires.

  • Améliorer la lisibilité et la maintenabilité de la classe,

  • Réduire les risques provoqués par les changements, les changements sont indispensables, si l'interface est à responsabilité unique est bien fait, une modification d'interface n'affectera que la classe correspondante et n'aura aucun impact sur les autres interfaces. Cela sera d'une grande aide pour l'évolutivité et la maintenabilité du système.

Remarque : Le principe de responsabilité unique propose une norme pour l'écriture de programmes, utilisant la « responsabilité » ou la « raison du changement » pour mesurer si la conception de l'interface ou de la classe est raisonnable, mais « responsabilité » et « raison du changement » n'ont pas de normes spécifiques. De quelles responsabilités une classe devrait-elle être responsable ? Comment ces responsabilités sont-elles détaillées ? Y aura-t-il une interface ou une classe après le raffinement ? Ceux-ci doivent être considérés en fonction de la situation réelle. Varie d’un projet à l’autre et d’un environnement à l’autre.

Exemple

Séparation de l'entité, du DAO, du service, du contrôleur, de l'utilitaire, etc. dans SpringMVC.

OOpen Closed Principe OCP

Open - ClosedPrinciple, OCP, ouvert pour extension, fermé pour modification (principe de base du modèle de conception)

Définition

Une entité logicielle (telle qu'une classe, un module et une fonction) doit être ouverte pour extension et fermée pour modification. Cela signifie qu'un système ou un module est ouvert aux extensions et fermé aux modifications. Un bon système peut étendre vos fonctions sans modifier le code source. La clé pour réaliser le principe d’ouverture et de fermeture est l’abstraction.

Analyse des principes

  • Lorsque les entités logicielles changent en raison des besoins, essayez d'étendre les entités logicielles existantes pour fournir de nouveaux comportements afin de répondre aux besoins du logiciel et de répondre aux nouveaux exigences au lieu de modifier le code existant, de sorte que le logiciel changeant ait un certain degré d'adaptabilité et de flexibilité. Les modules logiciels existants, en particulier les modules de couche d'abstraction les plus importants, ne peuvent pas être modifiés, ce qui confère au système logiciel en évolution un certain degré de stabilité et de continuité.

  • La clé pour réaliser le principe ouvert-fermé est l'abstraction : dans le principe "ouvert-fermé", les classes ou interfaces abstraites ne peuvent pas être modifiées, et les classes d'implémentation concrètes sont autorisées à étendre. ,Les classes abstraites et les interfaces jouent un rôle extrêmement important dans le principe "ouvert-fermé", c'est-à-dire prédire les changements possibles et prévoir toutes les extensions connues possibles. Donc "l'abstraction" est la clé ici !

  • Le principe fermé de variabilité : trouvez les facteurs variables du système et encapsulez-les. C'est la meilleure implémentation du principe "ouvert-fermé". Ne mettez pas vos facteurs variables dans plusieurs classes. , ou dispersés dans tous les coins du programme. Vous devez encapsuler les facteurs variables... et assurez-vous de ne pas encapsuler les facteurs variables que vous utilisez ensemble. La meilleure solution est d'enfermer vos variables dans des blocs. des cours super grands, des cours super longs et des méthodes super longues !! Ajoutez une saveur artistique à votre programme, et rendre le programme artistique est notre objectif

Exemple

Dans les modèles de conception, le modèle de méthode de modèle et le modèle d'observateur sont tous deux d'excellents modes de réalisation du principe d'ouverture et de fermeture. Cliquez ici pour consulter des explications détaillées sur 9 solutions pour la conception d'architectures à haute disponibilité.

Principe de substitution de Liskov LSP

Principe de substitution de Liskov, LSP : Partout où une classe de base peut apparaître, une sous-classe peut également apparaître. comme spécification de contrainte sur le mécanisme d'héritage.Ce n'est que lorsqu'une sous-classe peut remplacer sa classe de base que le système peut être assuré de reconnaître la sous-classe pendant l'exécution.C'est la base pour garantir la réutilisation de l'héritage.

Définition

La première façon de définition est relativement stricte : si pour tout objet o1 de type S, il existe un objet o2 de type T, de sorte que tous les objets définis avec T Lorsque tous les objets o1 du programme P sont remplacés par o2, le comportement du programme P ne change pas, alors le type S est un sous-type du type T.

La deuxième définition, plus facile à comprendre : tous les endroits qui font référence à la classe de base (classe parent) doivent pouvoir utiliser de manière transparente les objets de ses sous-classes. Autrement dit, la sous-classe doit pouvoir remplacer la classe de base d'où elle apparaît. Les sous-classes peuvent également ajouter de nouveaux comportements basés sur la classe de base.

(Le principe de substitution de Liskov a été proposé en 1994 par Barbara Liskov, lauréate du prix Turing 2008, première femme titulaire d'un doctorat en informatique aux États-Unis, professeur au MIT et professeur Jeannette Wing à Carnegie. Université Mellon. Le texte original est le suivant : Soit q(x) une propriété prouvable sur les objets x de type T. Alors q(y) devrait être vrai pour les objets y de type S où S est un sous-type de T. )

L'analyse des principes

  • concerne la relation entre les classes de base et les sous-classes. Ce n'est que lorsque cette relation existe que le principe de substitution de Liskov existe. Un carré est un rectangle est un exemple classique de compréhension du principe de substitution de Liskov.

  • Le principe de substitution de Liskov peut être exprimé d'une manière populaire : si vous pouvez utiliser des objets de classe de base dans un logiciel, alors vous devez être capable d'utiliser ses objets de sous-classe. Si la classe de base est remplacée par ses sous-classes, le programme ne générera aucune erreur ni exception. L'inverse n'est pas vrai. Si une entité logicielle utilise une sous-classe, elle ne pourra peut-être pas utiliser la classe de base.

  • Le principe de substitution de Liskov est l'un des moyens importants de mettre en œuvre le principe d'ouverture et de fermeture. Étant donné que les objets de sous-classe peuvent être utilisés partout où des objets de classe de base sont utilisés, les classes de base doivent être utilisées autant. autant que possible dans le programme. Tapez pour définir l'objet, puis déterminez son type de sous-classe au moment de l'exécution et remplacez l'objet de classe parent par l'objet de sous-classe.

Principe de ségrégation des interfaces

(Principe de ségrégation des interfaces, ISL) : Le client ne doit pas s'appuyer sur des interfaces dont il n'a pas besoin . (Cette loi est cohérente avec la loi de Demeter)

Définition

Le client ne doit pas s'appuyer sur des interfaces dont il n'a pas besoin.

Une autre méthode de définition : Une fois qu'une interface est trop grande, il faut la diviser en interfaces plus petites. Les clients utilisant l'interface n'ont besoin que de connaître les méthodes qui y sont liées.
Notez que l'interface dans cette définition fait référence à la méthode définie. Par exemple, appeler une méthode publique d’une classe depuis l’extérieur. Cette méthode est une interface avec le monde extérieur.

Analyse des principes

1) Le principe de l'isolation des interfaces fait référence à l'utilisation de plusieurs interfaces spécialisées au lieu d'utiliser une seule interface totale. Chaque interface doit assumer un rôle relativement indépendant, ni plus ni moins. Elle ne doit pas faire ce qu'elle ne devrait pas faire, mais doit faire tout ce qu'elle doit faire.

  • Une interface ne représente qu'un seul rôle, et chaque rôle a sa propre interface spécifique. Ce principe peut être appelé le « principe d'isolation des rôles ».

  • L'interface fournit uniquement les comportements dont le client a besoin, c'est-à-dire les méthodes requises dont le client n'a pas besoin sont masquées. Le client doit disposer d'une interface distincte. aussi petit que possible plutôt que de fournir une grande interface totale.

2) Lorsque vous utilisez le principe d'isolation d'interface pour diviser une interface, vous devez d'abord respecter le principe de responsabilité unique et définir un ensemble d'opérations associées dans une interface, et respecter le principe de haute cohésion. Moins il y a de méthodes dans l’interface, mieux c’est.

3) Des services personnalisés peuvent être utilisés lors de la conception du système, c'est-à-dire fournir des interfaces avec différentes largeurs et largeurs pour différents clients, fournir uniquement les comportements dont les utilisateurs ont besoin et masquer les comportements dont les utilisateurs n'ont pas besoin.

Principe d'inversion de dépendance DIP

Le principe d'inversion de dépendance doit s'appuyer sur l'abstraction plutôt que sur une implémentation spécifique. Plus précisément, les modules de haut niveau ne dépendent pas de Low. modules de niveau , qui dépendent tous deux d'abstractions. L'abstraction ne dépend pas du concret, le béton dépend de l'abstraction.

Définition

Les modules de haut niveau ne doivent pas dépendre de modules de bas niveau, ils doivent tous dépendre d'abstractions. Les abstractions ne devraient pas dépendre des détails, les détails devraient dépendre des abstractions. En termes simples, le principe d'inversion de dépendance oblige les clients à s'appuyer sur des couplages abstraits. Expression principale :

1) L'abstraction ne devrait pas dépendre des détails ; les détails devraient dépendre de l'abstraction

2) La programmation devrait être destinée aux interfaces, pas à l'implémentation ;

Analyse des principes

1) Si le principe d'ouverture et de fermeture est l'objectif de la conception orientée objet, le principe d'inversion de dépendance est le moyen d'atteindre le principe « d'ouverture et de fermeture » de l'objet- conception orientée. Si vous souhaitez obtenir le meilleur principe « d'ouverture et de fermeture », vous devez respecter autant que possible le principe d'inversion de dépendance. On peut dire que le principe d'inversion de dépendances est la meilleure spécification pour « l'abstraction » ! Personnellement, je pense que le principe d’inversion de dépendance est également un complément au principe de substitution de Richter. Une fois que vous avez compris le principe de substitution de Liskov, il devrait être facile de comprendre le principe d'inversion de dépendance.

2) L'un des moyens courants d'implémenter le principe d'inversion de dépendance consiste à utiliser des classes abstraites dans le code et à placer des classes concrètes dans le fichier de configuration.

3) Couplage entre classes : relation de couplage zéro, relation de couplage concrète, relation de couplage abstraite. Le principe d'inversion de dépendance oblige les clients à s'appuyer sur un couplage abstrait. Le couplage de manière abstraite est la clé du principe d'inversion de dépendance.

Exemple

Pour comprendre cette inversion de dépendance, nous devons d'abord comprendre le concept de dépendance dans la conception orientée objet :

Dépendance : C'est une relation d'usage, des choses spécifiques Les modifications peuvent affecter d'autres éléments qui utilisent cet élément. Utilisez des relations de dépendance lorsque vous devez indiquer qu'un élément en utilise un autre. (En supposant que les changements dans la classe A entraînent des changements dans la classe B, on dit alors que la classe B dépend de la classe A.) Dans la plupart des cas, la relation de dépendance se reflète dans la méthode d'une certaine classe utilisant un objet d'une autre classe comme paramètre. . En UML, les relations de dépendance sont représentées par des lignes pointillées avec des flèches pointant de la partie dépendante vers la partie dépendante.

Exemple : Un certain système fournit un module de conversion de données qui peut convertir les données de différentes sources de données en plusieurs formats, tels que les données d'une base de données (DatabaseSource) ou les données d'un fichier texte ( TextSource), le format converti peut être un fichier XML (XMLTransformer), un fichier XLS (XLSTransformer), etc.

Tous les architectes Java connaissent-ils ces 6 principes de conception ? Doit maîtriser

En raison de changements dans les exigences, le système peut devoir ajouter de nouvelles sources de données ou de nouveaux formats de fichiers à chaque fois qu'un nouveau type de source de données ou un nouveau type de fichier est ajouté. , Format, le code source de la classe client MainClass doit être modifié pour utiliser la nouvelle classe, mais cela viole le principe d'ouverture et de fermeture. Il est maintenant refactorisé en utilisant le principe d'inversion de dépendances. Cliquez ici pour consulter des explications détaillées sur 9 solutions pour la conception d'architectures à haute disponibilité.

Tous les architectes Java connaissent-ils ces 6 principes de conception ? Doit maîtriser

  • Bien entendu, selon la situation spécifique, AbstractSource peut également être injecté dans AbstractStransformer. Il existe trois méthodes d'injection de dépendances :

<ol class="hljs-ln list-paddingleft-2"><li><p class="hljs-ln-line"><span class="hljs-comment"><span class="hljs-comment">/** </span></span></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> * 依赖注入是依赖AbstractSource抽象注入的,而不是具体 </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">* DatabaseSource </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">* </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> */</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-keyword" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">abstract</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-class" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractStransformer</span> </span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">{  </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  </span><span class="hljs-keyword" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">private</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> AbstractSource source;  </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-comment">/** </span></span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  * 构造注入(Constructor Injection):通过构造函数注入实例变量。 </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">   */</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  </span><span class="hljs-function" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">AbstractStransformer</span><span class="hljs-params">(AbstractSource source)</span></span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">{  </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">     </span><span class="hljs-keyword" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">this</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">.source = source;          </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">   }  </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  </span><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-comment">/**      </span></span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">   * 设值注入(Setter Injection):通过Setter方法注入实例变量。 </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">   * </span><span class="hljs-doctag" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">@param</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> source : the sourceto set        </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">   */</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">      </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> </span><span class="hljs-function" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSource</span><span class="hljs-params">(AbstractSource source)</span> </span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">{            </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">    </span><span class="hljs-keyword" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">this</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">.source = source;            </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> }  </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  </span><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-comment">/** </span></span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">   * 接口注入(Interface Injection):通过接口方法注入实例变量。 </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  * </span><span class="hljs-doctag" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">@param</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> source </span><br/></p></li><li><p class="hljs-ln-numbers"><span class="hljs-comment" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">    */</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">  </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">   </span><span class="hljs-function" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transform</span><span class="hljs-params">(AbstractSource source )</span> </span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">{    </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">      source.getSource();  </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">    System.out.println(</span><span class="hljs-string" style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">“Stransforming …”</span><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">);    </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;"> }      </span><br/></p></li><li><p class="hljs-ln-numbers"><span style="font-family: "Microsoft Yahei", "Hiragino Sans GB", Helvetica, "Helvetica Neue", 微软雅黑, Tahoma, Arial, sans-serif;">}</span></p></li></ol>

Principe de réutilisation de composition/agrégation

(Principe de réutilisation composite/agrégat, CARP) : utiliser autant la combinaison d'objets Dans la mesure du possible, au lieu de la relation d'héritage pour atteindre l'objectif de réutilisation des logiciels

Définition

est souvent appelée le principe de réutilisation composite (Composite ReusePrinciple ou CRP). Essayez d'utiliser une combinaison d'objets. au lieu de l'héritage, atteindre l'objectif de réutilisation.

consiste à utiliser certains objets existants dans un nouvel objet pour les intégrer au nouvel objet ; le nouvel objet atteint l'objectif de réutiliser les fonctions existantes en déléguant à ces objets. En bref, essayez d'utiliser la composition/agrégation et essayez de ne pas utiliser l'héritage.

Analyse des principes

1) Dans la conception orientée objet, les conceptions et implémentations existantes peuvent être réutilisées dans différents environnements via deux méthodes de base, à savoir via des relations de combinaison/agrégation ou via l'héritage.

Héritage et réutilisation : simples à mettre en œuvre et faciles à étendre. Détruit l'encapsulation du système ; l'implémentation héritée de la classe de base est statique, ne peut pas être modifiée au moment de l'exécution et n'a pas suffisamment de flexibilité ; elle ne peut être utilisée que dans des environnements limités ; (Réutilisation "boîte blanche")

Réutilisation combinaison/agrégation : le degré de couplage est relativement faible et les opérations des objets membres sont appelées de manière sélective ; cela peut être effectué dynamiquement au moment de l'exécution. (Réutilisation "boîte noire")

2) La combinaison/agrégation peut rendre le système plus flexible, réduire le couplage entre les classes, et les changements dans une classe auront relativement peu d'impact sur les autres classes, donc généralement le premier choix consiste à utiliser la combinaison/agrégation pour réaliser la réutilisation ; deuxièmement, considérer l'héritage. Lorsque vous utilisez l'héritage, vous devez suivre strictement le principe de substitution de Liskov. Une utilisation efficace de l'héritage aidera à comprendre le problème et à réduire la complexité, tandis que l'abus de l'héritage entraînera une augmentation. la difficulté de construction et de maintenance du système et la complexité du système, la réutilisation de l'héritage doit donc être utilisée avec prudence.

3) Ce principe et le principe de substitution de Liskov sont complémentaires l'un de l'autre. Tous deux sont des spécifications pour la réalisation spécifique du principe "ouvert-fermé". En violant ce principe, le principe « ouvert-fermé » ne peut pas être réalisé. Tout d'abord, nous devons comprendre les concepts de synthèse et d'agrégation :

Remarque : Quelle est la différence entre l'agrégation et la combinaison ?

Synthèse (combinaison) : Indique la relation entre un tout et une partie, et fait référence à une relation qui existe basée sur le tout (le tout et les parties ne peuvent pas être séparés, par exemple, les yeux et la bouche sont une relation de combinaison) ; pour la tête, et sans la tête il n'y aurait pas d'yeux et de bouche, ils sont indissociables. En UML, les relations de composition sont représentées par des lignes droites avec des losanges pleins.

Agrégation : L'agrégation est une relation de dépendance plus forte que la relation de composition, et représente également la relation entre le tout et la partie (le tout et la partie peuvent être séparés comme la relation) ; entre les vis et les jouets de voiture, le jouet peut toujours être utilisé sur d'autres appareils une fois les vis détachées. En UML, les relations d'agrégation sont représentées par des lignes droites avec des losanges creux.

Loi de Déméter

(Loi de Déméter, LoD : classes dans le système, essayez de ne pas interagir avec d'autres classes, réduisez les classes Le Le degré de couplage entre

est défini sous plusieurs formes :

    Ne parlez pas à des inconnus.
  • Parlez uniquement à vos amis immédiats.
  • Chaque unité logicielle a une connaissance minimale des autres unités et est limitée aux unités logicielles qui sont étroitement liées à sa propre unité
  • . En termes simples, c'est-à-dire qu'un objet doit en savoir le moins possible sur les autres objets. Une classe doit en savoir le moins sur la classe qu'elle doit coupler ou appeler. Les éléments internes de vous (la classe couplée ou appelée) sont aussi compliqués. ça l'est, cela n'a pas d'importance pour moi. C'est votre affaire. Je ne connais que les méthodes publiques que vous proposez, je n'en appelle qu'un nombre limité. Catégories d'amis :

Dans la loi de Dimit, pour un objet, ses amis incluent les catégories suivantes : (1) L'objet courant lui-même (this) ; de l'objet actuel en tant que paramètre ; (3) L'objet membre de l'objet actuel ; (4) Si l'objet membre de l'objet actuel est un ensemble, alors les éléments de l'ensemble sont également amis (5) L'objet actuel ; L'objet créé.

Tout objet qui remplit l'une des conditions ci-dessus est un "ami" de l'objet actuel, sinon c'est un "étranger" :

    Au sens étroit de la loi de Déméter, si deux classes n'ont pas besoin de communiquer directement entre elles, alors les deux classes ne doivent pas communiquer directement entre elles. Fonction, si une classe a besoin d'appeler une méthode d'une autre classe. , l'appel peut être transmis via un tiers
  • Sens étroit de la loi de Dimit : cela peut réduire le couplage entre les classes, mais ce sera le cas en ajoutant un grand nombre de petites méthodes au système et en les éparpillant dans tous les coins. du système peut simplifier la conception locale d'un système, car chaque partie ne sera pas directement liée à des objets distants, mais cela entraînera également des différences dans le système. L'efficacité de la communication entre les modules est réduite, ce qui rend difficile la coordination entre les différents modules. du système. Cliquez ici pour voir les explications détaillées de 9 solutions pour la conception d'architectures à haute disponibilité

  • Loi de Demeter généralisée : fait référence à la relation entre les objets Le contrôle du flux d'informations, du flux et de l'impact est principalement le contrôle de. Dissimulation d'informations. La dissimulation d'informations peut découpler chaque sous-système, leur permettant d'être développés, optimisés, utilisés et modifiés indépendamment, et peut également favoriser la réutilisation des logiciels, car chaque module ne dépend pas d'autres modules, de sorte que chaque module peut être utilisé indépendamment dans d'autres. lieux. Plus un système est grand, plus il est important de cacher les informations, et plus l’importance de la dissimulation des informations devient évidente.

L’objectif principal de la loi de Déméter est de contrôler la surcharge d’informations.

  • En termes de division des classes, nous devrions essayer de créer des classes faiblement couplées. Plus le degré de couplage entre les classes est faible, plus une classe faiblement couplée est propice à la réutilisation. une classe est modifiée, cela n'aura pas beaucoup d'impact sur les classes associées ;

En termes de conception de la structure des classes, chaque classe doit minimiser ses variables membres et ses droits d'accès aux fonctions membres ; 🎜>

Dans la conception de classe, dans la mesure du possible, un type doit être conçu comme une classe immuable

  • En termes d'accès aux autres références de classe ; les références d'un objet à d'autres objets doivent être minimisées.

    • Exemple

    • Mode d'apparence Façade (type structurel)
    • Loi de Déméter et modèle de conception Mode façade, mode Médiateur

      Essayez de ne pas interagir avec d'autres classes du système pour réduire le couplage entre les classes, car dans votre système, lors de l'expansion, vous devrez peut-être modifier ces classes, et les classes sont différentes les unes des autres. elles déterminent la complexité de la modification. Plus il y a d'interactions, plus la difficulté de modification est grande. Au contraire, si les interactions sont plus petites, la difficulté de modification sera moindre. Par exemple, la classe A dépend de la classe B et la classe B dépend de la classe C. Lorsque vous modifiez la classe A, vous devez déterminer si la classe B sera affectée et si l'impact de la classe B affectera la classe C. Si la classe C dépend de la classe D en ce moment, haha, je pense que de telles modifications seront supportables.

      Questions et réponses

      Autres principes de la conception orientée objet

      Encapsulation des changements

      Utilisation moins d'héritage Composition polyvalente

      Ciblée sur la programmation d'interface et non sur la programmation d'implémentation

      S'efforcer d'obtenir une conception de couplage lâche entre les objets interactifs

      Les classes doivent être fermées au développement et à la modification d'extensions (ouvert et principe OCP fermé)

      Comptez sur des abstractions, ne comptez pas sur des classes concrètes (principe DIP d'inversion de dépendance)

      Principe de l'ami proche : ne parlez qu'à des amis (principe de moindre connaissance, loi de Déméter)

      Description : Un objet doit en savoir le moins possible sur les autres objets, garder les appels de méthodes dans les limites et appeler uniquement les méthodes qui appartiennent à la portée suivante : L'objet lui-même (méthodes locales) Les composants de l'objet sont transmis comme paramètres de méthode Objet Tout objet créé ou instancié par cette méthode

      Ne venez pas à moi (appelez-moi) Je viendrai à vous (vous appelle) (Principe d'Hollywood)

      A la classe n'a qu'une seule cause qui la fait changer (Principe de responsabilité unique SRP)

      Pouvez-vous expliquer le principe de substitution de Liskov

      Définition stricte : Si pour chaque objet o1 ? de type S, il existe un objet o2 de type T qui rend le comportement de tous les programmes P définis avec T inchangé lorsque tous les objets sont remplacés par o2 par o1, alors le type S est un sous-type de type T.

      Expression populaire : Tous les endroits qui font référence à une classe de base (classe parent) doivent pouvoir utiliser de manière transparente les objets de ses sous-classes. Autrement dit, une sous-classe peut étendre les fonctions de la classe parent, mais elle ne peut pas modifier les fonctions originales de la classe parent. Il contient les 4 niveaux de signification suivants :

      Une sous-classe peut implémenter la méthode abstraite de la classe parent, mais ne peut pas remplacer la méthode non abstraite de la classe parent.

      Les sous-classes peuvent ajouter leurs propres méthodes uniques.

      Lorsqu'une méthode d'une sous-classe remplace une méthode d'une classe parent, les conditions préalables de la méthode (c'est-à-dire les paramètres formels de la méthode) sont plus souples que les paramètres d'entrée de la méthode de la classe parent.

      Lorsqu'une méthode d'une sous-classe implémente une méthode abstraite d'une classe parent, les postconditions de la méthode (c'est-à-dire la valeur de retour de la méthode) sont plus strictes que celles de la classe parent.

      Dans quelles circonstances la loi de Déméter serait-elle violée ? Pourquoi est-ce un problème ?

      La loi de Demit recommande de « ne parler qu'à des amis, pas à des inconnus » pour réduire les couplages entre les cours.

      Donnez-moi un exemple de modèle de conception conforme au principe ouvert-fermé ?

      Le principe ouvert-fermé nécessite que votre code soit ouvert pour extension et fermé pour modification. Cela signifie que si vous souhaitez ajouter une nouvelle fonctionnalité, vous pouvez facilement ajouter un nouveau code sans modifier le code déjà testé. Il existe plusieurs modèles de conception basés sur le principe d'ouverture-fermeture, comme le modèle de stratégie. Si vous avez besoin d'une nouvelle stratégie, il vous suffit d'implémenter l'interface et d'ajouter une configuration, sans modifier la logique de base. Un exemple fonctionnel est la méthode Collections.sort(). Elle est basée sur le modèle de stratégie et suit le principe ouvert-fermé. Vous n'avez pas besoin de modifier la méthode sort() pour les nouveaux objets. propre interface de comparaison.

      Quand utiliser le mode poids mouche (mode poids mouche) ?

      Le mode Flyweight évite de créer trop d'objets en partageant des objets. Pour utiliser le modèle flyweight, vous devez vous assurer que vos objets sont immuables afin de pouvoir les partager en toute sécurité. Le pool String, le pool Integer et le pool Long dans le JDK sont tous de bons exemples d'utilisation du modèle Flyweight.

      fin :

      Si vous avez des questions, vous pouvez les poser et discutons-en ensemble.

      Articles connexes :

      Connaissances de base que JavaScript doit connaître

      24 modèles de conception et 7 principes en Java

      Vidéos associées :

      Tutoriel vidéo de conception de framework avancé JavaScript

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn