-- IPersonIO.java -- public interface IPersonIO { public abstract void save(Person p); }
Jeg vil dog gerne have en løsning hvor PersonSQL implementer IPersonIO interfacet. Derudover ville jeg gerne kunne ændre save() metoden i Person.java til noget lignende:
public void save(){ IPersonIO.save(this); }
Så jeg ikke kalder PersonSQL men kun interfacet. Grunden til at jeg gerne vil have denne løsning er at hvis jeg på et andet tidspunkt hellere ville gemme objektet i en fil så kan jeg blot udskrifte PersonSQL med PersonGemObjektIFil som ligeledes skulle implentere IPersonIO.
Skriv endelig hvis jeg har været uklar i min problembeskrivelse.
Jeg håber der er nogen der kan hjælpe mig med at få lavet løsningen, for det har ikke kunne lykkedes for mig.
I mine øjne er din opbygning næsten rigtig som den er nu. Jeg ville dog ikke have en save metode på Person-klassen, da det giver en høj kobling til din IPersonIO implementation.
Hvis du endelig VIL ha' Person-klassen til at have ansvaret for at gemme, kan du smide en IPersonIO implementation med i constructoren på din Person-klasse. Men umiddelbart bryder jeg mig ikke om den løsning.
Når jeg nærlæser dit spørgsmål, så forstår jeg det sådan, at det du efterlyser er hvordan du kan køre på interfacet og kun på interfacet?
Det kan du ikke. Der skal altid oprettes en instans af en klasse der implementerer dit interface. Så du kan ikke undgå: new PersonSQL(); eller andre klasser der implementerer interfacet.
Jeg kan desværre ikke lige få forbindelse til min database nu men jeg tænkte på om dette kunne være en fornuftig løsning og i denne løsning har jeg inddraget mikkelbm's forslag om at Person ikke selv skal gemme objektet. Men som sagt har jeg ikke kunne kontrollere om det virker.
Det er vel meget smart at man både kan tilføje en klasse der gemmer objektet i databasen og en klasse der gemmer samme objekt i en fil, så man har en backup hvis netforbindelsen smutter. Men så kan jeg ikke lige gennemskue hvordan man henter alle personer fra databasen/filen uden at få dobbelt poster da begge klasser jo vil blive hente person objekterne.
Efter min mening er det en god idé at holde sig til én måde at gemme sine data på. Fordelen ved interfacet er at du kan skifte til at gemme på disken, hvis du af en eller anden grund ikke længere kan bruge databasen. Med det mener jeg ikke, at du i 5 minutter ikke kan bruge database, men at måden hvorpå du gemmer dine objekter laves om til at bruge disken fremover.
Håber du forstår.
Det kan også være at der er nogen der kan give en god og fornuftig grund til at gemme begge steder - jeg kan bare ikke umiddelbart.
Det forekommer lidt naturstridig med et interface der specifikt refererer (i parameteren) til den klasse det skal være interface for. Hvad er så fidusen ved overhovedet at have et interface der ?
Interfacet skjuler vel implementationen af hvordan man ønsker sit objekt gemt. Men ja, man kunne sagtens lave et interface, som Person skal implementere for at kunne bruge save metoden - hvis det er det du tænker på?
Nu har jeg siddet og kigget nærmere på min egen løsning. Jeg løber bare ind i problemet med at der på nuværende tidspunkt ikke er nogen af klasserne der opretter en instans af PersonSQL klassen. Hvordan løser jeg dette problem så løsningen stadig forbliver løst koblet? Hvis jeg giver Controller ansvaret så er jeg jo tilbage hvor jeg startede.
Jeg vil mene at det er din controllers ansvar at oprette instansen er PersonSQL klassen. Og du er ikke tilbage hvor du startede, da du fra starten havde lagt ansvaret inde i Person-klassen.
Og hvis vi skal tage lidt udgangspunkt i Jakobs kommentar, om at et interface ikke er nødvendigt i dette tilfælde, kan vi gøre følgende for at et interface netop er på sin plads her.
Hvis vi tænker den lidt længere. I øjeblikket har du en høj kobling, da du i interfacet tager Person-klassen med som parameter. Dette kan løses ved at lade Person nedarve fra et interface dedikeret til dette - og hvis vi så tager et skridt yderligere, kan du faktisk lave starten på dit eget persistens-framework.
Et lille hurtigt udkast:
// Først et interface som alle objekter der skal persisteres/gemmes skal nedarve fra // Jeg har lavet en metode der returnerer et id, da man i mange tilfælde vil ha' brug // for dette i forbindelse med database. Du kan undlade den i første omgang, // hvis ikke du mener der er relevant public interface PersistencyObject { public int getId (); }
// Nu kommer så dit eget interface (omdøbt så det ikke indikerer direkte at det har med Person at gør) // - nu med et PersistencyObject som parameter public interface ISaver { public void save(PersistencyObject obj); }
// Ovenstående er så dit eget lille framework, der udbyder nogle interfaces der kan bruges til at gemme objekter. // Nu kommer så implementationen:
// Implementation af din Person-klasse public class Person implements PersistencyObject { private int id;
public Person (int id) { this.id = id; }
public int getId () { return id; }
// Og alle de andre metoder du har på dit Person-objekt }
// Implementation af din PersonSQL public class PersonSQL implements ISaver { public void save(PersistencyObject p) { if (p instanceof Person) { Person person = (Person)p; // Gem dit objekt i databasen } }
// eventuelle andre hjælpemetoder... }
Ved ovenstående har du en klar adskillelse og løst koblet system. Din controller skal stadig ha' ansvaret for at oprette en instans af PersonSQL klassen, men det er i mine øjne også det helt rigtige sted at gøre det.
Håber du kan bruge det. Spørg bare hvis du er i tvivl om noget.
Jeg formoder at du vil oprette PersonSQL instansen i Controller klassen med denne linje: ISaver PersonSaver = new PersonSQL();?
Nu er mit spørgsmål så om det er nødvendigt at kontrollere om PersistencyObject objektet er et Person objekt? Ville dette ikke kun være nødvendigt hvis jeg havde en general SQL klasse som gemmer forskellige PersistencyObject objekter? f.eks.: if (p instanceof Person) { Person person = (Person)p; // Gem Person objekt i databasen } if (p instanceof Dyr) { Dyr dyr = (Dyr)p; // Gem Dyr objekt i databasen }
"Jeg formoder at du vil oprette PersonSQL instansen i Controller klassen med denne linje: ISaver PersonSaver = new PersonSQL();?"
- Lige præcis
Og til dit andet spørgsmål, så kan du faktisk godt have lidt ret i det. Det var blot en sikkerhedsforanstaltning, så du ikke vil få en InvalidCastException, når du prøver at caste til et Person-objekt. vil du kunne gemme et andet objekt, f.eks. 'Dyr', så vil jeg anbefale at du laver en klasse/mapper til det, da det hurtigt bliver noget rod med at gemme forskellige ting i samme klasse. Man kunne også sagtens forestille sig, at du også vil hente objekterne igen, og derfor smider en ny metode på interfacet - det vil være meget nemmere at implementere, hvis ansvaret er fordelt på forskellige klasser, der ved præcist hvordan de forskellige objekter skal gemmes.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.