1
votes

Décorer un cours concret, mauvaise pratique?

Les schémas uml typiques du modèle de conception de décorateur sont les suivants: https://www.dofactory.com/net/decorator-design-pattern

ils montrent que le décorateur est autour d'une interface.

La question est, est-ce vraiment important que c'est une interface ou une classe concrète ?

Pour commencer, un décorateur n'est pas censé taper sur le comportement de l'objet enveloppé, c'est simplement un calque de fonctionnalité. Donc je ne vois pas en quoi c'est plus risqué que d'utiliser l'interface.

En général, je voudrais (aimerais) décorer comme ça:

class Foo{
    public void doSmth(){
    }
}
class LoggedFoo extends Foo{
    private Foo wrappedFoo;
    public LoggedFoo(Foo foo){wrappedFoo = foo;}
    @override
    public void doSmth(){
        System.out.println("doSmth start");
        wrappedFoo.doSmth();
        System.out.println("doSmth end");
    }
}

Je ne Je pense que nous devrions regarder l'héritage de classe concret à la seule vue parce que "c'est dangereux". Alors, interface ou classe concrète, est-ce important ici?


5 commentaires

Cela n'a jamais d'importance - le fait est, comme toujours, qu'il est généralement plus propre d'implémenter des interfaces, en évitant d'être verrouillé sur une classe concrète.


Les interfaces permettent à une classe d'implémenter plusieurs interfaces, mais pas la classe concrète


Eh bien, un décorateur ne prolonge jamais qu'une classe


Cela "compte" dans le sens où ce n'est pas le motif du décorateur.


Michael Tu dis ça parce que j'ai laissé de côté l'élément "décorateur abstrait" entre Foo et LoggedFoo?


3 Réponses :


0
votes

Vous devriez utiliser des interfaces car c'est la meilleure pratique. Ils sont plus faciles à tester et à modifier l'implémentation. Que faire si vous souhaitez utiliser différents types d'enregistreurs en production (base de données, fichier, console, etc.)?


1 commentaires

Dans le cas de différents enregistreurs, je décorerais simplement de la même manière, une instance de LoggedFoo peut être décorée sans accroc avec un autre décorateur.



2
votes

C'est important car l'idée même des Decorators est d'ajouter des fonctionnalités sans passer par la voie de l'héritage d'implémentation. Si vous êtes d'accord avec l'héritage d'implémentation et que vous risquez de changer le comportement existant de l'objet, vous n'avez pas du tout besoin d'un décorateur.

L'idée générale est d'étendre la fonctionnalité sans rompre le comportement existant, ce que fait l'héritage d'implémentation.


1 commentaires

Le contrat autour d'une classe est écrit au plus haut niveau de la hiérarchie d'héritage, que le parent de niveau supérieur soit une interface ou une classe. Ce contrat pourrait également être rompu si le parent était une interface.



2
votes

L'extension d'une classe peut avoir des effets secondaires indésirables.

Si Foo a déjà un constructeur (ou plusieurs), vous devez également les implémenter et appeler la super classe.

De plus, si Foo a un état privé ou des effets secondaires dans le constructeur, ceux-ci sont maintenant exécutés deux fois . Une fois pour le Foo passé dans le constructeur et une fois pour le LoggedFoo, qui est aussi un Foo.

Cela pourrait devenir compliqué et entraîner des bogues et une consommation accrue de ressources, mais cela dépend entièrement de la classe. Si la classe se comporte comme une interface (constructeur par défaut, pas d'effets secondaires, pas d'état), il se peut que ce ne soit pas directement un problème. Mais à ce stade, ce serait juste une sous-classe qui appelle une autre instance, ce qui peut être une construction pratique mais je ne l'appellerais pas en utilisant le modèle décorateur.


3 commentaires

C'est un aspect intéressant


@Sheed Cette classe enveloppe maintenant un Foo, appelons-le foo1, et il est un Foo lui-même: foo2. Ainsi, lorsque vous utilisez cette classe, il existe au moins deux Foo. La décoration des interfaces n'a pas cet effet.


Oui, j'ai supprimé mon commentaire après avoir réalisé que les membres privés pouvaient encore exister et être initialisés sans que j'appelle le constructeur.