![translation](https://cdn.durumis.com/common/trans.png)
Ceci est un post traduit par IA.
[Objet] Chapitre 2. Programmation orientée objet
- Langue de rédaction : Coréen
- •
-
Pays de référence : Tous les pays
- •
- Technologies de l'information
Choisir la langue
Texte résumé par l'IA durumis
- Il décrit la manière de mettre en œuvre un système de réservation de billets de cinéma à l'aide de la programmation orientée objet, présente les concepts de collaboration, d'objets et de classes, et souligne l'importance d'une structure de programme qui suit la structure du domaine.
- Il propose en particulier une méthode pour réduire les interférences externes et garantir la liberté des programmeurs grâce à l'autonomie des objets et à l'encapsulation, en séparant les interfaces et les implémentations.
- Il explique également comment écrire du code flexible et extensible en utilisant la collaboration, l'héritage et le polymorphisme pour calculer les tarifs réduits, et souligne l'importance de l'abstraction et les avantages de la composition pour la réutilisation du code.
Système de réservation de billets de cinéma
Examen des exigences
- Nous essayons d'implémenter un système de réservation de billets de cinéma en ligne.
- Le film représente les informations de base sur un film.
- Titre, heure de projection, informations sur les prix, etc.
- La projection représente l'événement réel pendant lequel le public regarde le film.
- Date de projection, heure, numéro de projection, etc.
- Les gens réservent des billets de cinéma, mais en réalité, ils devraient réserver des billets pour une projectionspécifique.
- Conditions de réduction
- Disponibilité de rabais sur le prix
- Conditions de classement : utiliser le numéro de projection pour déterminer si un rabais est applicable
- Conditions de durée : utiliser l'heure de début de la projection pour déterminer si un rabais est applicable
- Politique de réduction
- Déterminer le tarif réduit
- Politique de réduction de prix : déduction d'un montant fixe des frais de réservation
- Politique de réduction proportionnelle : déduction d'un pourcentage fixe du prix plein tarif
- Un film peut avoir une seule politique de réduction ou aucune, et plusieurs conditions de réduction peuvent être combinées.
- Si une politique de réduction est appliquée mais que les conditions de réduction ne sont pas remplies, ou si aucune politique de réduction n'est appliquée, les frais ne sont pas réduits.
Vers la programmation orientée objet
Collaboration, objets, classes
- La programmation orientée objet est axée sur les objets.
- Une fois que vous avez décidé de la classe, vous ne devriez pas vous demander quelles sont les attributs et les méthodes nécessaires à la classe.
- Vous devez déterminer quels objets ont quel état et quel comportement.
- Les objets ne doivent pas être considérés comme des entités indépendantes, mais comme des membres d'une communauté collaborative.
Structure de programme qui suit la structure du domaine
- Le domaine fait référence au domaine dans lequel les utilisateurs utilisent le programme pour résoudre un problème.
- En règle générale, le nom d'une classe doit être identique ou du moins similaire au nom du concept de domaine correspondant.
- La relation entre les classes doit également être aussi similaire que possible à la relation établie entre les concepts de domaine afin de rendre la structure du programme plus facile à comprendre et à prévoir.
Implémentation de classes
- Une classe est divisée en interne et en externe, et pour concevoir une bonne classe, vous devez décider quelles parties rendre publiques et quelles parties masquer.
- Les attributs d'un objet sont masqués en privé, et les méthodes nécessaires pour modifier l'état interne sont ouvertes en public.
- La distinction entre l'intérieur et l'extérieur d'une classe garantit l'autonomie de l'objet, ce qui offre aux programmeurs la liberté d'implémentation.
Objet autonome
- Un objet doit être un objet autonome avec un état et un comportement.
- Le regroupement des données et des fonctions à l'intérieur de l'objet est appelé encapsulation.
- Le contrôle d'accès doit être utilisé pour réduire les interférences externes afin que l'objet puisse prendre ses propres décisions concernant son comportement.
- Le principe de séparation de l'interface et de l'implémentation est un principe majeur qui doit être suivi pour la programmation orientée objet.
- Interface publique : partie accessible de l'extérieur
- Implémentation : partie accessible uniquement en interne
Liberté du programmeur
- Le rôle du programmeur est divisé en auteur de classe et programmeur client.
- L'auteur de la classe ajoute un nouveau type de données
- Le programmeur client utilise le type de données ajouté par l'auteur de la classe
- Masquage de l'implémentation
- L'auteur de la classe peut fournir uniquement les parties nécessaires au programmeur client et masquer l'implémentation interne.
- Le programmeur client n'a besoin de connaître que l'interface, ce qui réduit la quantité de connaissances.
Communauté d'objets collaboratifs
- Lors de la représentation de l'argent, il est préférable d'envelopper une variable de type Long dans un objet, tel que Money. L'utilisation d'un objet permet de mieux conveyer le sens et de gérer les calculs redondants en un seul endroit.
- L'interaction qui a lieu entre les objets pour implémenter une certaine fonctionnalité du système est appelée collaboration.
Une courte histoire sur la collaboration
- La seule façon pour un objet d'interagir avec un autre objet est d'envoyer ou de recevoir des messages.
- Une méthode est un moyen spécifique de gérer les messages reçus.
- Il est important de distinguer les messages des méthodes, car c'est là que commence le concept de polymorphisme.
Calcul des frais de réduction
Début de la collaboration pour le calcul des frais de réduction
- La classe Movie ne contient pas de logique détaillée concernant la politique de réduction et l'a déléguée à l'interface DiscountPolicy. L'héritage, le polymorphisme et l'abstraction sont vraiment importants.
Politique de réduction et conditions de réduction
Héritage et polymorphisme
Dépendance au moment de la compilation et dépendance au moment de l'exécution
- La dépendance du code et la dépendance au moment de l'exécution peuvent être différentes.
- Plus la dépendance entre les deux est différente, plus le code est difficile à comprendre, mais plus il est flexible et extensible.
Programmation basée sur les différences
- L'héritage permet d'ajouter facilement et rapidement de nouvelles classes basées sur les classes existantes, et il est possible de réutiliser l'implémentation de la classe parent.
- La création de nouvelles classes en ajoutant uniquement les parties qui diffèrent de la classe parent est appelée programmation basée sur les différences.
Héritage et interfaces
- L'héritage permet aux classes enfants d'hériter de toutes les interfaces fournies par la classe parent.
- Une interface définit une liste de messages qu'un objet peut comprendre.
public class Movie {
public Money calculateMovieFee(Screening screening) {
return fee.minus(discountPolicy.calculateDiscountAmount(screening));
}
- Movie envoie un message calculateDiscountAmount à DiscountPolicy. Movie ne se soucie pas de la classe de l'instance qui répond, il lui suffit que la réponse soit donnée avec succès.
- Par conséquent, AmountDiscountPolicy et PercentDiscountPolicy peuvent tous deux collaborer avec Movie à la place de DiscountPolicy.
- Ce type de remplacement de la classe enfant par la classe parent est appelé conversion ascendante. En effet, la classe enfant semble être convertie automatiquement en classe parent au moment du typage.
Polymorphisme
- Le polymorphisme est la capacité d'un objet à répondre différemment selon son type lorsqu'il reçoit le même message.
- Movie envoie le même message, mais la méthode qui sera effectivement exécutée dépend de la classe de l'objet qui reçoit le message.
- Le polymorphisme repose sur le fait que la dépendance au moment de la compilation et la dépendance au moment de l'exécution d'un programme peuvent être différentes.
- Le polymorphisme détermine la méthode à exécuter au moment de l'exécution, il est donc appelé liaison différée ou liaison dynamique.
Interfaces et polymorphisme
- Si vous ne souhaitez pas partager l'implémentation mais souhaitez uniquement partager l'interface, vous pouvez utiliser une interface au lieu d'une classe abstraite.
Abstraction et flexibilité
Le pouvoir de l'abstraction
- Avantages de l'abstraction
- Si vous examinez uniquement la hiérarchie d'abstraction, vous pouvez décrire la politique des exigences à un niveau élevé.
- La conception devient plus flexible.
Conception flexible
- L'abstraction empêche la conception d'être liée à des situations spécifiques, ce qui permet de créer une conception flexible.
Classe abstraite et compromis d'interface
public abstract class DiscountPolicy {
private List conditions;
public DiscountPolicy(DiscountCondition... conditions) {
this.conditions = Arrays.asList(conditions);
}
public Money calculateDiscountAmount(Screening screening) {
for (DiscountCondition condition : conditions) {
if (condition.isSatisfiedBy(screening)) {
return getDiscountAmount(screening);
}
}
return Money.ZERO;
}
abstract protected Money getDiscountAmount(Screening screening);
}
public class NoneDiscountPolicy extends DiscountPolicy {
@Override
protected Money getDiscountAmount(Screening screening) {
return Money.ZERO;
}
- Actuellement, NoneDiscountPolicy n'est pas vraiment un problème car calculateDiscountAmount() de DiscountPolicy renvoie 0 s'il n'y a pas de conditions de réduction. Cependant, du point de vue de l'utilisateur, il faut ajouter une politique None qui ne présente pas de conditions de réduction en tant qu'argument de Movie.
- Par conséquent, la classe NoneDiscountPolicy est déroutante conceptuellement, il est donc préférable de la modifier comme suit pour une meilleure compréhension.
public interface DiscountPolicy {
Money calculdateDiscountAmount(Screening screening);
}
public abstract class DefaultDiscountPolicy implements DiscountPolicy {
private List conditions;
public DefaultDiscountPolicy(DiscountCondition... conditions) {
this.conditions = Arrays.asList(conditions);
}
public Money calculateDiscountAmount(Screening screening) {
for (DiscountCondition condition : conditions) {
if (condition.isSatisfiedBy(screening)) {
return getDiscountAmount(screening);
}
}
return Money.ZERO;
}
abstract protected Money getDiscountAmount(Screening screening);
}
public class NoneDiscountPolicy implements DiscountPolicy {
@Override
public Money calculateDiscountAmount(Screening screening) {
return Money.ZERO;
}
}
public class PercentDiscountPolicy extends DefaultDiscountPolicy {
private double percent;
public PercentDiscountPolicy(double percent, DiscountCondition... conditions) {
super(conditions);
this.percent = percent;
}
@Override
protected Money getDiscountAmount(Screening screening) {
return screening.getMovieFee().times(percent);
}
}
public class AmountDiscountPolicy extends DefaultDiscountPolicy {
private Money discountAmount;
public AmountDiscountPolicy(Money discountAmount, DiscountCondition... conditions) {
super(conditions);
this.discountAmount = discountAmount;
}
@Override
protected Money getDiscountAmount(Screening screening) {
return discountAmount;
}
- Comme indiqué ci-dessus, DiscountPolicy est abstraite en tant qu'interface et ses implémentations sont divisées en NoneDiscountPolicy et DefaultDiscountPolicy, qui représente une politique de réduction générale.
- L'ajout d'une interface uniquement pour NoneDiscountPolicy peut sembler moins efficace que l'augmentation de la complexité.
- Vous devez comprendre que tout ce qui est lié à l'implémentation peut être un compromis. En d'autres termes, tout code que vous écrivez doit avoir une raison d'être.
Réutilisation du code
- L'héritage peut être utilisé pour réutiliser le code.
- Mais il est préférable d'utiliser la composition plutôt que l'héritage pour la réutilisation du code.
- La façon dont Movie réutilise le code de DiscountPolicy dans le code actuel est la composition.
- Si vous définissez Movie comme une classe supérieure et que vous la divisez en AmountDiscountMovie et PercentDiscountMovie, cela signifie que vous utilisez l'héritage.
Héritage
- Inconvénients de l'héritage
- Viole l'encapsulation.
- Vous devez bien connaître la structure interne de la classe parent.
- La probabilité que la classe enfant doive également être modifiée lors d'une modification de la classe parent est élevée.
- Rend la conception moins flexible.
- La relation entre la classe parent et la classe enfant est déterminée au moment de la compilation.
- Il est impossible de modifier le type d'objet au moment de l'exécution.
- Cependant, la composition permet de remplacer l'instance au moment de l'exécution via une méthode telle que changeDiscountPolicy() dans la classe utilisant l'objet.
- Viole l'encapsulation.
Composition
- La composition consiste à réutiliser du code uniquement via des messages définis dans une interface.
- L'encapsulation peut être implémentée et un couplage lâche peut être maintenu.
- Pour le polymorphisme, l'héritage et la composition doivent être combinés.
- Par exemple, l'interface DiscountPolicy doit utiliser l'héritage pour implémenter des implémentations inférieures.
Source
- Objet