2010-03-24 2 views
0

J'ai une classe AdjacencyListGraph fonctionnelle qui adhère à une interface GraphStructure définie. Pour la couche des limites sur ce (par exemple acyclique, non nulles, les données de sommets uniques, etc..), Je vois deux voies possibles, chaque utilisation faisant de l'interface GraphStructure:Limitations graphiques - Dois-je utiliser Decorator?

  1. Créer une seule classe ("ControlledGraph") qui a un ensemble de bitflags spécifiant diverses limitations possibles. Gérer toutes les limitations de cette classe. Mettez à jour la classe si de nouvelles exigences de limitation deviennent apparentes. Utilisez le motif décorateur (DI, essentiellement) pour créer une implémentation de classe distincte pour chaque limitation individuelle qu'une classe de client peut souhaiter utiliser. L'avantage ici est que nous adhérons au principe de la responsabilité unique.

Je pencherais vers ce dernier, mais par Jove !, je déteste le décorateur Pattern. C'est l'incarnation du fouillis, IMO. En vérité, tout dépend du nombre de décorateurs qui pourraient être appliqués dans le pire des cas - dans le mien jusqu'à présent, le nombre est de sept (le nombre de limitations discrètes que j'ai reconnu à ce stade). L'autre problème avec le décorateur est que je vais devoir faire un wrapping de méthode d'interface dans chaque classe de décorateur. Bah.

Lequel voulez-vous, si non? Ou, si vous pouvez proposer une solution plus élégante, ce serait la bienvenue. EDIT: Il me semble que l'utilisation de la classe ControlledGraph proposée avec le modèle de stratégie peut aider ici ... une sorte de configuration de méthode de modèle/foncteurs, avec des bits individuels appliquant des contrôles séparés dans les différentes méthodes d'interface graphique-canonique. Ou suis-je perdre l'intrigue?

+0

@ Nick Wiggill: J'irais avec un décorateur (qui peut être utilisé à la fois pour ajouter et, moins connu, pour supprimer les responsabilités) mais pourquoi détester? C'est le contraire de l'encombrement: sans un décorateur, vous finirez avec encombrement et l'évier de la cuisine dans votre ControlledGraph. Notez que les IDE modernes peuvent générer tous les appels délégués au sujet enveloppé dans le raccourci * one *. L'un des principaux points d'OO fait correctement est de pouvoir s'adapter aux exigences en constante évolution. Si les exigences sont gravées dans la pierre, alors en fonction d'une implémentation (ControlledGraph) qui utilise des champs de bits peut être OK, mais ce n'est pas OO. – SyntaxT3rr0r

+0

Je suis d'accord avec vous, c'est pourquoi j'ai mentionné le SRP. Je peux vous dire que j'ai déjà une version à moitié complète de cette implémentation particulière qui se trouve ici, et ce n'est * pas * joli. Mais voir ma réponse ci-dessous et vous verrez une solution plus élégante qui encapsule la fonctionnalité pour chaque limitation, fournissant une architecture beaucoup plus extensible, et sans le fouillis de décorateur (c'est encombrer - je suis désolé mais un niveau indéterminé de constructeur nidification est tout simplement idiot). –

Répondre

0

Ah, je le vois maintenant. Le modèle de stratégie dans une classe ControlledGraph est en effet le chemin à parcourir.

Chaque limitation est une classe de stratégie discrète. Chacune d'entre elles implémente l'intégralité de l'interface GraphStructure, bien que la plupart des méthodes restent vides (par exemple, une limitation acyclique ne s'intéresse qu'à l'utilisation de addEdge() pour empêcher les insertions de cycle, les autres méthodes resteront vides).

Chaque fois que le ControlledGraph a une de ses méthodes d'interface appelée, il appelle les méthodes de correspondance de chacune des stratégies/limitations qu'il contient. Il peut ne contenir qu'un seul de chaque type de stratégie, évidemment.