J'ai une structure de classe qui représente (en interne) les données que je souhaite sortir à un fichier.
Certaines variables de membre sont privées à la classe de données afin qu'elle puisse se gérer et empêcher les choses qui vont faire face. p>
i alors je veux que ces données soient émises dans un certain nombre de formats de fichiers. Je pourrais faire quelque chose comme p> sauf que les fonctions doivent ensuite voir les variables de membre privé de existe un modèle de conception standard pour résoudre ce genre de chose? Comment résoudriez-vous ce problème? P> Merci! P> P> DataClass code>. Je pouvais bien sûr juste faire des fonctions code> sauvegardes_formatxyz () code>, mais je devrais ensuite ajouter une déclaration d'ami pour chaque format différent. P>
7 Réponses :
La solution habituelle serait de décider quelles données doivent être exportées, et de fournir une sorte d'accès (probablement des fonctions getter). Logiquement, vous ne voulez pas que la classe elle-même ait à connaître des détails sur les formats, et vous ne voulez pas que les formates sachent quoi que ce soit plus sur la classe que les données qu'il doit formater. p>
En effet, j'ai pensé à cela, mais les données pourraient être importantes afin que tous les getters auraient besoin de passer par référence / pointeur. Mais cela ne fait-il pas casser l'encapsulation aussi?
@Dan, n ° Les interfaces publiques sont bien contrôlées par votre classe pendant que l'ami n'est pas. Considérez que vous ajoutez plus de données privées dans votre futur de la classe de données, que vous ne voulez pas exposer à des formateurs. Si vous utilisez une classe d'amis, vous n'avez aucun moyen de l'empêcher.
Original supprimé: Je répondais à une autre question. Si vous émettez les données sur un support externe, ce n'est pas vraiment privé de toute façon. Les getters retourneront des références ou des valeurs constantes, elles ne permettront donc pas de modifier (contrairement à ami code>). Et puisque les getters sont pour la mise en forme, les performances ne seront pas un problème de toute façon; Vous voudrez peut-être définir une structure artificielle avec toutes les données, et simplement avoir un seul getter le renvoyant par la valeur.
Je pense que le problème que vous avez ici est l'un des design. Serializing à un fichier ne doit pas être modifier em> que des données de toute façon, alors pourquoi ces fonctions doivent-elles être privées? Si tout ce que vous faites, c'est examiner les données et l'écriture, vous devriez avoir une interface publique adéquate. P>
Rien ne devrait modifier les données, mais tout le point d'encapsulation consiste à empêcher les gens de faire accidentellement des choses qu'ils ne devraient pas.
@Dan, mais si vous fournissez un accès «ami» à vos exportateurs, vous ne pouvez-ils pas faire quelque chose qu'ils ne devraient pas? Si vous avez besoin de transmettre des références autour, passez Const B> Références autour de.
Ne recourez pas toujours à une fonction d'ami car elle peut facilement casser l'encapsulation de votre classe. Une fois ami, il peut accéder à tous vos membres privés, que vous espérez que cela puisse voir ou non. p>
Dans votre cas, vous pouvez simplement fournir des interfaces publiques pour renvoyer les données nécessaires aux clients qui produiront des formats différents alors. De plus, vous pouvez regarder le célèbre motif MVC A> Si vous êtes intéressé. P>
C'est une mauvaise réponse. Un ami ne casse que l'encapsulation du point de vue de la classe une i> tous les autres clients restent encapsulés. Lorsque vous utilisez une interface publique pour renvoyer les données, alors l'encapsulation est cassée pour tout le monde i>.
@Deadmg, ce n'est pas le cas. Une interface bien définie n'affecte que l'encapsulation de la classe actuelle sans affecter les clients. Il appartient aux clients de décider d'utiliser cette interface ou non. Cela ne signifie pas nécessairement que le client devrait également modifier leur interface.
@Deadmg, un autre avantage de l'interface publique est que vous pouvez bien définir les configurateurs et les getters séparément, ce qui ne peut pas être contrôlé par un ami.
La meilleure chose à laquelle je puisse penser pour votre problème (de conception) est une solution de deux fois:
Fonctionnez des fonctions génériques qui économisent de XML à n'importe quel format souhaité: P>
savefile_formatA(XMLNode* pRootNode, ofstream& fout);
+1. Bonne idée, bit surkill pour mon projet actuel, mais je vais garder à l'esprit.
En fonction de la complexité de votre classe de données, vous souhaiterez peut-être utiliser un motif de visiteur. Si vous avez une sorte de structure de données imbriquée, le visiteur peut bien être ce dont vous avez besoin.
Si la mise en forme est quelque chose de relativement simple, vous produisez par exemple des variations sur quelque chose comme une liste séparée par des virgules, alors vous pouvez adopter une approche comme celle-ci. . p>
Vos objets de formateur Tout mettre en place une interface telle que (pseudo code) p> alors la classe de données a une méthode p> Cela rend la classe formatée responsable du choix des données à formater et le formateur responsable des détails du format. P> p>
Si vous devez implémenter le formatage du fichier et enregistrer / charger de dehors em> de la classe, vous ne pouvez le faire que avec des données publiquement disponibles. Si l'enregistrement / le chargement doit traiter des données non publiques, si le rechargement de la classe ne peut pas reconstruire les données originales non publiques des données publiques, la classe elle-même ou les amis de cette classe doit être impliquée. Il n'y a pas vraiment un moyen de contourner cela. Le plus vous pourriez être capable de faire est de faciliter la rédaction de nouveaux types, avec un modèle d'ami. Par exemple: P> template<> void SaveFile<FormatA>(const DataType *, ofstream&);
template<> void SaveFile<FormatB>(const DataType *, ofstream&);
Combiné avec le visiteur ci-dessus est la solution parfaite.
Vous en feriez une méthode sur Dataclass et passez dans le flux. p>
Quels formats voulez-vous dire? Vous envisagez de formats génériques comme .txt .xls .doc ou un format privé spécifique à chaque classe?