8
votes

Classe de base vs classe utilitaire

Lequel des deux devrait être préféré?

Il y a quelques méthodes appelées par classe A, B et C.

Si ces méthodes sont encapsulées dans une classe D (base d'A, B et C)?

ou

Si ces méthodes sont encapsulées dans une classe U et d'autres classes crée son objet d'utiliser les méthodes requises.

sur quelle décision de base devrait être prise?

merci.


3 commentaires

Y a-t-il une relation conceptuelle entre les classes A, B et C?


Que diriez-vous de faire une interface et de mettre en œuvre cela par A, B, C?


@P: Seulement qu'ils construisent des données utilisées par la classe D. A nécessitent des entrées différentes que d'autres classes. @Srinivas: La mise en œuvre de ces méthodes est exactement la même pour A, B et C.


4 Réponses :


12
votes

Vous devez créer un Static classe utilitaire.

Utilisez uniquement l'héritage s'il est réellement significatif-si a , b et c effectivement est a a code> d .


5 commentaires

Oui je suppose. D a des méthodes qui invoquent certains algorithmes de trois types. A, B et C Construire des données spécifiques à l'algorithme et appelez ces méthodes courantes d'exécution.


@Azo: Détail aide toujours. Dans ce cas, vous devriez peut-être utiliser l'héritage, avec une méthode abstraite par A , B et c .


Je suis totalement d'accord avec votre deuxième point, mais je ne conseillerais que l'utilisation d'une classe d'utilité statique où les méthodes utilitaires n'ont aucun état (I.e aucune variables statiques) et n'active aucune opération avec des effets secondaires (fichier IO ou activité de la base de données, etc.). Si vous êtes unitaire Test A, B et C, il est (presque) impossible de les découpler d'une classe d'utilité statique avec des objets simulés. Il est bien préférable d'utiliser une classe utilitaire non statique transmise à A / B / C via une injection de constructeur. Ensuite, votre code est hautement configurable et acquiert des comportements via une agrégation.


@Azodius - Jetez un coup d'œil au modèle de conception de la stratégie ( en.wikipedia.org/wiki/strategy_pattern). Vous avez une classe de base abstraite et des sous-classes qui personnalisent l'algorithme. Cela ressemble exactement à ce dont vous avez besoin.


@XCAL: Vous avez raison, mais vous faites des hypothèses injustifiées sur la qualité de son codeBase.



2
votes

Je subirais loin de l'héritage à moins qu'il y ait une relation "forte> évidente" une relation . Je soupçonne de votre description ci-dessus que ce n'est pas le cas. Mes solutions préférées seraient:

  1. injecter une instance d'une classe d'utilité dans votre A, B, C
  2. avoir un, B, C instanciez les classes utilitaires appropriées

    L'avantage de l'injection de la classe est que vous pouvez fournir différentes implémentations de manière triviale. Ceci est particulièrement utile pour les tests. Les singletons ou les classes avec des méthodes statiques ont tendance à causer des problèmes pour la même raison - vous ne pouvez pas les remplacer facilement ou les substituer.


0 commentaires

3
votes

Je vais baser la décision sur ce que les méthodes font, s'ils font des choses spécifiques aux classes A, B et C, alors ils devraient être dans la classe de base. Cela aide à garder le code propre, en masquant ainsi la fonctionnalité liée à la classe du reste du système. (Bien sûr, je suppose que A, B et C héritent déjà de D, ou sont évidemment liés)

S'ils font des choses avec d'autres types, qui ne sont pas inhérents à ce que A, B et C font, alors afin de maximiser les possibilités de réutilisation, ils devraient être dans une classe d'utilité.

S'ils font des choses avec d'autres types spécifiques à cet autre type (par exemple, une jolie imprimante d'une date d'heure) envisagez de les faire des méthodes d'extension pour que Type.


1 commentaires

+1: Tu m'as battus. Comme le mentionne Slaks, il semble également que l'OP ne soit pas au courant des fonctions statiques. Peut-être la peine de mentionner cela aussi pour la classe d'utilité.



-1
votes

Utilisez la classe de base Si vous allez écrire une certaine logique uniquement en fonction de la classe de base - il est logique de créer une classe de base. Dans ce cas, votre classe dérivée devrait être complètement substituable pour votre classe de base. Il ne devrait pas y avoir de logique de commutation pour vérifier le type dérivé et agir en conséquence. Voir le principe de substitution de Liskov: http://en.wikipedia.org/wiki/liskov_substitution_principe

Utiliser classe utilitaire Certaines langues ont la limitation qu'ils ne soutiennent pas de multiples héritages. Si vous avez déjà une classe de base significative, vous devez choisir la classe de services publics. En outre, lorsque vous utilisez l'héritage, vous créez un couplage étroit entre la classe dervée à la classe de base.

J'irais pour la classe de base si la classe dérivée est naturellement substituable pour sa classe de base. Si le but est de partager un code réutilisable entre les classes, il a plus de sens d'aller avec la classe de services publics.


0 commentaires