Change log
Home
|
Gebruik geen globale variabelen.
Globale variabelen zou je willen gebruiken voor gegevens die in de hele applicatie
gelijk zijn, en ook overal in de applicatie worden aangesproken dan wel geraadpleegd.
Een voorbeeld hiervoor zou kunnen zijn de achtergrondkleur van verschillende windows
waarbij de gebruiker een eigen kleur kan kiezen. Maar ook aanlog gegevens van de
gebruiker, zodat zijn persoonlijk profiel wordt gebruikt, of waarmee hij zich aanmeldt
bij een server op het web die aangesproken wordt door de applicatie (bijv. een newsserver,
messenger-server).
Een eerste , maar voor de hand liggende methode om globale variabelen te vermijden
zou zijn, om deze gegevens mee te geven aan objecten, zodat deze hiervan op de hoogte
zijn. Nadelen van deze oplossing:
-
Het is arbeidsintensief
-
Het object weet nooit of de gegevens up-to-date zijn
- Als de gegevens via een ander object (waar deze gegevens als een verzameling in
zitten) worden doorgegeven met een reference, je nooit weet of het object waar je
naar toe verwijst nog bestaat.
Een andere manier is een object in het leven te roepen, dat maar een maal in de
applicatie kan bestaan.
- De class kan slechts een maal en niet meer dan een maal worden geinstantieërd.
Dit kun je realiseren door een class een instance van zichzelf te laten teruggeven.
Als dit object op dat moment nog niet bestaat dan maakt het zichzelf aan, in het
andere geval geeft het zichzelf terug.
Het typische van zo'n class is dat het geen public constructor heeft, je kunt het
alleen aanspreken via z'n Instance method of property/getter
De oplossing waarbij een class slechts een maal kan worden gecreeërd, wordt een
Singleton pattern genoemd.
Opmerkingen bij de Singleton implementaties.
Wat opvalt bij een inheritable Singleton, zoals hier geimplementeerd, is dat de
Factory verantwoordelijk is voor het bijhouden van de static variabele, niet de
Singleton zelf, hierdoor heeft het Singleton pattern op zich geen interne functionaliteit.
Het is een abstract begrip geworden.
Creational versus behavioral
Alhoewel de Singleton vrijwel altijd als creational wordt gezien, het draait om
de instantiëring, wordt het soms beschouwd als een behavioral pattern, het laat
zich slechts een maal instantiëren, dus de manier waarop. Met de implementatie zoals
hier beschreven ligt de nadruk eigenlijk alleen nog maar op het gedrag, het creationele
deel is naar de Factory verschoven.
Scope.
-
Binnen een method heeft het begrip Singleton geen betekenis.
-
Binnen een class wordt de rol van Singleton gespeeld door static variabelen. Als
deze variabele een object representeerd, dan moet dit er een zijn die binnen de
class is geinstantieërd.
-
Binnen een applicatie is dit het Singleton pattern.
- Op een netwerk (eventueel wereldwijd) zijn dit Singletons die in een Web-service
(instances van objecten), Applicatie-server (instances van objecten), Sql-server(rijen
in tabellen), of iedere willekeurige andere server aanwezig zijn. Zo een Singleton
is (meestal) niet rechtstreeks te benaderen, een gebruikelijke oplossing hiervoor
is een proxy pattern (remote) of een facade (tabel in een database), hierdoor is
het alsof de Singleton zich binnen de applicatie zelf bevindt.
De SingletonFactory.
Deze wordt in de voorbeelden niet geïnstanteërd, dit is ook niet nodig, omdat de
methods waarmee de Singeltons worden aangemaakt zelf ook static zijn, het zijn class
methods. Dit maakt de SingletonFactory een uitzonderlijke Factory. Er is echter
niets wat het creëren van de Factory tegenhoudt, omdat deze impliciet zelf ook het
gedrag van een Singleton vertoond. Wat er dan gebeurt is dat je meerdere deurtjes
naar een en hetzelfde object aanmaakt. Een soort van wormholes in applicatie-space
die allemaal op dezelfde plek terechtkomen, waardoor de Singleton min of meer omni-present
wordt.
Het afschermen van de implementatie details.
Dit wordt vaak aangedragen als noodzakelijk, om misbruik van de Singleton tegen
te gaan, zoals het aanmaken van een tweede instance van een Singleton, of het clonen
van een instance. Met andere woorden, kwade opzet. Onzin, als je dit probeert heb
je niet in de gaten wat je aan het doen bent, er is geen enkele reden om zoiets
te doen, simpelweg omdat het geen meerwaarde heeft en er alleen maar fouten in de
applicatie worden geintroduceerd. Het afschermen is bedoeld om te voorkomen
dat er per ongeluk fouten worden gemaakt, door dit soort acties onmogelijk te maken.
Alhoewel de Delphi en C# uitvoeringen vrijwel identiek zijn, kunnen er toch verschillen
aangewezen worden.
-
De basis Factory in delphi geeft een TSingleton terug ipv een ISingleton, dit komt
doordat in delphi een interface niet rijker kan worden gecast. Omdat in delphi
een com-interface wordt teruggegeven, is er eenvoudigweg niets aanwezig om te casten,
bij een class is dit wel het geval. Opgemerkt moet worden dat een interface in Delphi
niet 'zuiver' is.
-
Verder is een concreet classType nodig om te instantiëren, het gevolg daarvan is
weer dat de class die we doorgeven aan de factory om te creëren ook echt afgeleid
moet zijn van een TSingleton. Dit scheelt weer een check en een exception, maar
kan het lastiger maken om een bestaande class van een Singleton af te leiden.
- Daarnaast moet de Singleton instance een verwijzing naar zijn eigen interface
vasthouden. Dit om te voorkomen dat de Singleton op een reference=0 terechtkomt
en wordt vrijgegeven.
|