«StringBuilder» est-il une application du modèle de conception Builder?

31

Le modèle "Builder" est-il limité à la lutte contre l'anti-modèle "constructeur télescopique", ou peut-on dire qu'il aborde également le problème plus général de la création compliquée d'objets immuables?

La StringBuilderclasse a le mot «constructeur» dans son nom, mais cela n'a rien à voir avec les constructeurs télescopiques, cela nous aide simplement à collecter toutes les données dont nous avons besoin pour passer au constructeur d'un objet immuable.

Pour moi, il semble que la réponse soit un «oui» très clair, mais il semble y avoir un certain désaccord sur le sujet, alors j'espérais que quelqu'un pourrait peut-être le clarifier.

Je répondais à cette question: Programmeurs SE: légitime «vrai travail» chez un constructeur? où l'OP veut créer un objet (vraisemblablement immuable) contenant un arbre complexe, et l'idée du modèle "constructeur" est apparue, et en le recherchant, j'ai trouvé ce Q&R qui semble dire que le style de création d'objet "StringBuilder" est pas une application du modèle "Builder", pour des raisons qui ne sont pas claires pour moi: Stackoverflow - StringBuilder et Builder Pattern . (Ceux qui ont répondu à cette question n'ont pas réussi à convaincre autant que je sache.)

Mike Nakis
la source
2
Je trouve la réponse de Paul Sasik à cette question de Stack Overflow entièrement convaincante: StringBuilder est une "solution de contournement" pour le problème de performances de la concaténation de chaînes immuables, rien de plus. Au mieux, StringBuilder est «malheureusement nommé». Vous pourriez faire valoir que StringBuilder peut "construire" des pages Web, je suppose, mais c'est une application spécifique d'un mécanisme général.
Robert Harvey
3
La réponse de Paul Sasik est fausse pour Java - j'ai regardé le code source sous-jacent. StringBuildersemble utiliser un tableau de caractères sous-jacent pour représenter la chaîne et vous permet de faire des choses comme des insertions et des suppressions à tout moment. En fin de compte, je pense que StringBuilder est une solution de contournement pour les objets String immuables, mais il me semble par ailleurs qu'il répond à l'intention du modèle Builder.
Thomas Owens
4
Je dois y penser beaucoup plus - cela me dérange. J'ai presque commencé à écrire pourquoi quelque chose comme StringBuilder est une version du modèle Builder et que tout le monde avait tort. Mais j'ai trouvé quelques faiblesses, je me suis convaincu que j'avais tort, mais j'ai réussi à revenir à ma première pensée. Si vous regardez uniquement l'intention du modèle de générateur, il est facile de voir que "StringBuilder est un générateur". Si vous regardez la structure du modèle Builder, c'est plus difficile.
Thomas Owens
1
Pour ce que ça vaut, cette réponse sur Stack Overflow est d'accord avec ma pensée initiale que StringBuilder est une implémentation de générateur et les commentaires sont intéressants. Vous pouvez donc trouver les deux côtés de l'argument. Je suis favorable à cette question - je ne sais pas si je peux construire une bonne réponse, mais c'est une question intéressante à coup sûr. J'y penserai.
Thomas Owens
2
Tous les modèles du GoF ne résistent pas à l'épreuve du temps. Je ne suis pas en train de dire , je dis juste.
Ben

Réponses:

36

A StringBuilderest similaire à un modèle de générateur, mais ne partage pas beaucoup avec la description GoF de ce modèle de conception. Le point d'origine du motif de conception était

Séparez la construction d'un objet complexe de sa représentation afin que le même processus de construction puisse créer des représentations différentes.

- de Design Patterns , par Gamma, Helm, Johnson, Vlissides.

(note: «complexe» signifie principalement «composé de plusieurs parties», pas nécessairement «compliqué» ou «difficile»)

Les «différentes représentations» sont essentielles ici. Par exemple, en supposant ce processus de construction:

interface ArticleBuilder {
  void addTitle(String title);
  void addParagraph(String paragraph);
}

void createArticle(ArticeBuilder articleBuilder) {
  articleBuilder.addTitle("Is String Builder an application of ...");
  articleBuilder.addParagraph("Is the Builder Pattern restricted...");
  articleBuilder.addParagraph("The StringBuilder class ...");
}

nous pourrions nous retrouver avec un HtmlDocumentou un TexDocumentou un en MarkdownDocumentfonction de la mise en œuvre concrète fournie:

class HtmlDocumentBuilder implements ArticleBuilder {
  ...
  HtmlDocument getResult();
}

HtmlDocumentBuilder b = new HtmlDocumentBuilder();
createArticle(b);
HtmlDocument dom = b.getResult();

Donc, un point central du motif Builder est le polymorphisme . Le livre Design Patterns compare ce modèle à la fabrique abstraite:

Abstract Factory est similaire au Builder dans la mesure où il peut également construire des objets complexes. La principale différence est que le modèle Builder se concentre sur la construction d'un objet complexe étape par étape. […] Builder retourne le produit comme étape finale, mais en ce qui concerne l'usine abstraite, le produit est retourné immédiatement.

- de Design Patterns , par Gamma, Helm, Johnson, Vlissides.

Cet aspect étape par étape est alors devenu l'aspect le plus populaire du modèle Builder, de sorte que dans le langage courant, le modèle Builder est compris comme suit:

Scinder la construction d'un objet en plusieurs étapes. Cela nous permet d'utiliser des arguments nommés ou des paramètres facultatifs même dans des langues qui ne prennent pas en charge ces fonctionnalités.

Wikipedia définit le modèle comme ceci:

Le modèle de générateur est un modèle de conception de logiciel de création d'objet. Contrairement au modèle d'usine abstrait et au modèle de méthode d'usine dont l'intention est de permettre le polymorphisme, l'intention du modèle constructeur est de trouver une solution à l'anti-modèle du constructeur télescopique [citation nécessaire] . […]

Le modèle de générateur présente un autre avantage. Il peut être utilisé pour des objets contenant des données plates (code html, requête SQL, certificat X.509 ...), c'est-à-dire des données difficilement éditables. Ce type de données ne peut pas être modifié étape par étape et doit être modifié en une seule fois. La meilleure façon de construire un tel objet est d'utiliser une classe de générateur. [citation requise]

- de Builder Pattern sur Wikipédia , par divers contributeurs.

Donc, comme nous pouvons le voir, il n'y a pas de compréhension vraiment commune du modèle auquel ce nom fait référence, et sur certains points, différentes définitions se contredisent même (par exemple en ce qui concerne la pertinence du polymorphisme pour les constructeurs).

La seule propriété commune du StringBuilderavec diverses interprétations du motif est que le produit est créé étape par étape plutôt qu'en une seule fois. Il ne répond pas à une lecture stricte de la définition du modèle de conception du GoF, mais veuillez noter que les modèles de conception sont des concepts malléables destinés à faciliter la communication. Je continuerais d'appeler StringBuilderun exemple du modèle Builder, bien qu'atypique - la principale raison de cette structure en Java est une concaténation performante en présence de chaînes immuables, mais pas une conception orientée objet intéressante.

Amon
la source
7
Il me semble que la création d'objets immuables semble être l'une des utilisations les plus courantes des constructeurs - je pense que cela a remplacé l'utilisation principale telle que décrite par GoF, alors convenez que c'est certainement mieux décrit comme une instance du modèle.
Jules
Acceptez l'utilisation dans la création de graphiques immuables, une autre utilisation pour les DSL Builder est vraiment utile pour créer de grands graphiques de fausses données / ObjectMothers pendant les tests unitaires et d'intégration.
StuartLC