Classe Saver d'une classe X - Friend et encapsulation
Voila, je voulais avoir votre avis sur un petit problème de design.
En effet, je dispose d'une classe X qui matérialise des entités dans un espace physique.
Ces entités doivent pouvoir être chargées et sauvegardées depuis différentes sources : un format de fichier, une base de donnée, etc...
Mais, avec tous les articles théoriques que je digère en ce moment, je me pose beaucoup de questions sur la bonne solution à adopter
Pour préserver l'encapsulation, j'ai décidé de ne pas exposer les données internes de X, juste des méthodes (translate(), rotate()). En revanche, il parait évident qu'une classe en particulier doit pouvoir accéder à ces données internes : la classe qui se charge des sauvegardes.
J'en arrive donc à un dilemme : le sain principe de l'encapsulation me défend d'exposer les entrailles de X, et pourtant on peut estimer que la classe Saver est "au dessus de ça".
Une solution serait de confier à X le soin de se sauvegarder elle même, mais ça me semble "bloater" les attributions de X, qui ne devrait pas avoir à se soucier de la manière dont elle est gérée (donc sauvegardée).
La solution qui vient tout de suite à l'esprit, c'est de déclarer Saver::save(X* x) friend de ma classe X.
Sauf que la classe Saver est une interface, et que le friendship ne s'hérite pas, et que je ne sais pas à l'avance quels classes dérivées l'utilisateur va implémenter. Donc friend ne résout pas mon problème, en tout cas pas comme ça.
Une solution pas trés élégante serait de déclarer Saver friend de ma classe X, et de créer un getter protected pour chaque attribut de X, que les classes dérivées de Saver appeleraient.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
class Saver;
class X
{
friend Saver;
//...
};
class Saver
{
//...
protected:
std::string getIdentifier(X* x) { return x->mIdentifier; }
Vector3 getPosition(X* x) { return x->mPosition; }
Vector3 getVelocity(X* x) { return x->mVelocity; }
}; |
Mais du coup ça me demande de mettre à jour mon interface Saver ET ses implémentations à chaque modification de la classe X.
Je recquiert donc vos avis éclairés sur cette question : y-a-t il d'autres manières de voir le problème, d'autre solutions ?