[OO] Implementatie Singleton pattern

Pagina: 1
Acties:
  • 189 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 30-07 17:20

JHS

Splitting the thaum.

Topicstarter
Hoi :) .

Na af en toe wat testcases voor Webdesign, Markup & Clientside Scripting in elkaar proberen te hebben geprutst leek het me ook wel 's leuk en handig om die voor veelvoorkomende problemen / patterns in PRG / SEA te maken, zoals (de PHP code) voor een Singleton. Ik begon enthousiast aan een Singleton class, maar ik sloeg er helaas niet in een in mijn ogen ideale implementatie te realiseren. Idealiter gezien zou het in mijn ogen zo moeten werken:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
abstract class Singleton {
  /* implementation */
}

class A extends Singleton {
  /* child functions */
}

$a = new A();
$a->set_foo("bar");
echo $a->foo; /* should display bar */

$b = new A();
echo $b->foo; /* should display bar */
Ik kon echter geen bevredigende implementatie vinden. Hetgeen het meest in de buurt kwam was het volgende:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
abstract class Singleton {
    private $instance;
    
    protected final function __construct() {
        if(method_exists($this, "construct")) {
            $this->construct();
        }
    }
    
    public static function get_instance() {
        if(!isset(self::$instance)) {
            $class = __CLASS__; /* This creates the problem, 
                as it refers to the Singleton class, instead of the A class */
            self::$instance = new $class;
        }
        return self::$instance;
    }
}

class A extends Singleton {
    private $a;
    
    public function set($a) {
        $this->a = $a;
    }

    public function output() {
        echo $this->a;
    }
}

$a = A::get_instance();
$a->set("foo");
$a->output(); /* Should output foo */
$b = A::get_instance();
$b->output(); /* Should output foo */
Maar dit werkt niet, aangezien de __CLASS__ constant in Singleton verwijst naar Singleton zelf, en niet naar het aangeroepen child A.

Natuurlijk zou het $class probleem op te lossen door in A een protected $class="A"; op te nemen. Ook zou je door een get_instance function op te nemen, met daarin parent::get_instance(__CLASS__); in het singleton child (A), en de get_instance method in de parent om te bouwen naar een die een $class argument accepteert. Maar dat lijkt me beide niet echt gewenst, aangezien je dan een deel van hetgeen je met de parent class wil realiseren verplaatst naar de child.

Een andere manier zou met een Factory (achtige) class zijn, maar dat vond ik ook niet helemaal bevredigend, aangezien dat, wederom, betekend dat de client op de hoogte moet zijn van het feit dat de aangeroepen class een singleton is.

Ook een Registry (achtige) class zou het kunnen oplossen, doordat je dan de classname van de beoogde class doorgeeft aan het object dat hem moet aanmaken. Maar ook dit lijkt me niet ideaal, aangezien, wederom, het voor de aanroepende class gaat boeien of het een singleton is of niet.

Of maak ik nu een enorme denkfout, en hoort die verantwoordelijkheid sowieso niet bij de singleton-zijnde class?

In de comments op php.net werd verder gesuggereerd dat het sowieso niet de bedoeling is om het te willen oplossen, aangezien singleton een pattern is, en geen class. Is dit een zinnig commentaar, of is het toch juist om het op de bovenstaande manier te willen implementeren?

Kortom: hoe kan ik het Singleton pattern het beste implementeren :) .

In overleg met * Creepy in Software Engineering & Architecture geplaatst :) .

DM!


Acties:
  • 0 Henk 'm!

  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05 09:40

GX

Nee.

Hm,

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Singleton
{
    static protected $_instance = false;

    function __construct()
    {
        printf ("het werkt\n");
    }

    static function Singleton()
    {
        if (self::$_instance == false)
            self::$_instance = new self();
    }
}

$test = Singleton::Singleton();


Snel in psuedo-meuk neergetikt; maar dit is bijna dezelfde als wat jij had. Ik dacht dat ik het ooit zo opgelost had.
Vergeef me overigens voor m'n php-vergeetachtigheid, het is wat lang geleden

edit:
Even snel hercode en uitgeprobeerd

[ Voor 31% gewijzigd door GX op 24-03-2006 16:45 ]


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Waarom zou je een abstracte class maken waar jouw Singletons van overerven ?
Waarom zou je uberhaupt een base class maken voor dit ?

Het singleton pattern zegt dat je slechts 1 instantie mag hebben. Echter, als jij een base class maakt, waar je verschillende classes van laat overerven (inherited class IS A base class), waar zit die 'constraint' dan nog ?
Je kan dan bv van iedere inherited class wel juist één instantie hebben, maar deze classes zijn eigenlijk ook base-classes, en dan heb je dus meerdere instanties van je base class.

En waarom zou de client niet mogen weten dat de aangeroepen class een singleton is ? Het is juist de bedoeling dat je client dat wel weet imho. Op die manier weet je client dat hij geen instanties van die singleton kan aanmaken, maar enkel de 'one and only' instantie van die singleton class kan opvragen.

Een singleton wordt daarom op deze manier geimplementeerd:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Singleton
{
     private Singleton()
     {
     }

     private static Singleton _instance;

     public static Singleton Instance
     {
       get
        {
            if( _instance == null )
                  _instance = new Singleton();

            return _instance;
        }
     }
}

Op die manier kan de client gewoon geen instance maken, en, weet de client dat hij enkel de Singleton instantie kan benaderen door de static Property Instance aan te spreken.
zware topicstart, zo voor de vrijdagavond...

[ Voor 28% gewijzigd door whoami op 24-03-2006 16:49 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 30-07 17:20

JHS

Splitting the thaum.

Topicstarter
GX: Op zich werkt het wil, totdat je hem wil extenden :) . Het implementeren van een Singleton an sich was dan ook het probleem niet, maar meer het mogelijk maken van een Singleton Base Class die te extenden viel.

whoami: Ik wil graag een base class omdat ik niet in elke class die een singleton is dezelfde functionaliteit wil gaan zitten aanmaken :) .

En op zich heb je gelijk dat ik dan meerdere Singleton instanties heb, wat op zich niet helemaal klopt, aangezien je dan in de parent een behaviour (het niet meer dan één instantie hebben) implementeerd wat hij zelf niet mag uitvoeren. Maar het vermijden van dubbelle functionaliteit / eigenschappen lijkt me relevanter? Ik dacht altijd dat als je in meerdere classes dezelfde functionaliteit, en in dit geval zelfs dezelfde code, zit toe te voegen je wat fout doet :) .

Misschien heb je wel gelijk dat de client best van het feit dat je een singleton class aanroept moet afweten, maar moet ik daarom gelijk een SingletonFactory / Registry class gaan opzetten? Of de non-functionaliteit-repeating practice opgeven, waarbij ik ervanuit ga dat dat iets slechts is..

DM!


Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 19:59

RayNbow

Kirika <3

Subclassing Singletons with Java 5.0 O-)
(Interessant draadje om te lezen)

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Misschien leuk om te weten:
Singletons zijn erg fijn: het is onzin om meerdere instancies van een object aan te maken, vooral als het dure objecten zijn of de instantie gewoon gedeeld moet worden.

De vraag is alleen of het Singleton design pattern wel zo handig is. In het begin was ik helemaal kapot van de Singleton design pattern omdat je dus geen gedonder meer hebt om aan object referenties te komen. Het probleem zit hem echter in een paar zaken:
-Systemen met singletons zijn meestal lastiger te testen omdat je dus niet altijd controle hebt over een dependency
-Systemen met singleton zijn minder helder omdat het niet meteen duidelijk is welke dependencies een object heeft.
-Systemen met singleton zijn vaak minder goed uitbreidbaar omdat je concrete implementaties door de keel krijgt gedrukt (eigelijk is dit ook de oorzaak van het 1e probleem)

Sinds ik in aanraking gekomen ben met IOC-containers heb ik bijna geen Singleton meer gemaakt. Misschien kun je daar eens naar kijken (alhoewel ik betwijfel of er IOC containers zijn voor PHP).

Een ander punt om op te letten is concurrency problematiek bij het maken van de singleton. Ik weet verder niet veel (zeg maar niets) van PHP af, dus ik weet ook niet hoe dit systeem zich gedraagd mbt threading. Maar bij Java zijn er veel problemen geweest (zoek maar eens op The "Double-Checked Locking is Broken" Declaration

[ Voor 11% gewijzigd door Alarmnummer op 24-03-2006 17:45 ]


Acties:
  • 0 Henk 'm!

  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 07-09 09:59
als je singleton wil subclassen dan ga je toch 1 of andere registry moeten bijhouden met de verschillende soorten in je Base klasse, maar dat doet dan weer je hele oorspronkelijk opzet teniet...

ik zou me de vraag stellen waarom je een base klasse wil... over het algemeen zijn singletons niet overdreven veel aanwezig in een applicatie, dus als jij alle stap een singleton aanmaakt dan ben je misschien verkeerd bezig en zou je misschien best je design van je applicatie eens herzien.

"Live as if you were to die tomorrow. Learn as if you were to live forever"


Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Met Java 5 kun je inderdaad gemakkelijk GoF patterns herbruikbaar opzetten. Het lijkt me alleen vrij sterk dat zulke grappen gemakkelijk te realiseren zijn in PHP, waar je geen generics hebt. (tenminste voor zover ik PHP ken (dat is overigens niet veel))

Aan de andere kant is PHP een scripttaal zonder strict typing, waardoor zoiets misschien wel in elkaar te 'hacken' valt. De vraag is alleen of je op die manier een beetje betrouwbare code krijgt.

Fat Pizza's pizza, they are big and they are cheezy


Acties:
  • 0 Henk 'm!

  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 30-07 17:20

JHS

Splitting the thaum.

Topicstarter
Alarmnummer: Waarom zijn "systemen met singleton zijn vaak minder goed uitbreidbaar omdat je concrete implementaties door de keel krijgt gedrukt", ervanuitgaande dat je ze kan subclassen :) ? En waarom zijn "systemen met singleton zijn minder helder omdat het niet meteen duidelijk is welke dependencies een object heeft."

Ik snap ook eerlijkgezegd niet helemaal waarom IOC voorkomt dat je singletons nodig hebt? Omdat het framework zelf ervanuit kan gaan dat er maar een instantie van, bijvoorbeeld, DomDocument bestaan? Tenminste, ik begreep uit de link die je gaf dat IOC betekend dat de controll voor bijvoorbeeld iets naar een beeldscherm brengen (realisatie van de output) verplaatst van de applicatie naar je framework.

Cuball: De huidige opzet die ik in mijn gedachten had was zoiets:
code:
1
2
3
4
5
abstract class Singleton
abstract class DatabaseAccess extends Singleton { }
class MysqlDatabaseAccess extends DatabaseAccess { }
class (...)DatabaseAccess extends DatabaseAccess { }
class DomDocument extends Singleton { }

DM!


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Waarom zou je ze moeten gaan subclassen ?

Inheritance is een mooie uitvinding, maar ze moet -imho- ook 'verstandig' gebruikt worden. In de meeste gevallen moet je het Liskov principe kunnen toepassen; maw, je moet kunnen programmeren tegen het 'base' type, terwijl dat base-type een referentie kan bevatten naar een inherited type.

Ik ben zelf nog niet zo 'into' IoC ~ik moet er maar eens wat meer over lezen / spelen / zien ~, maar een singleton gebruik ik ook niet zo heel veel. Wat ik meestal heb , is een ApplicationSettings singleton class, die bv een NHibernate SessionFactory factory bevat, zodanig dat ik zeker ben dat ik die SessionFactory slechts 1x hoef aan te maken.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
JHS schreef op vrijdag 24 maart 2006 @ 18:41:
Alarmnummer: Waarom zijn "systemen met singleton zijn vaak minder goed uitbreidbaar omdat je concrete implementaties door de keel krijgt gedrukt", ervanuitgaande dat je ze kan subclassen :) ?
Singletons worden (vaak) niet als parameters doorgegeven, maar in een methode zelf aangemaakt/opgehaald. Door middel van een static call naar een getInstance() method op een concrete class. Met als nadelige gevolg dat je niet meer tegen een abstracte weergave van een object (zoals een interface) aan praat tegen de contrete class.
Dat je kan subclassen helpt niet veel aangezien je in het hierboven genoemde scenario een dergelijke manier van intancieren krijgt:
PHP:
1
2
3
public function buy() {
     $customer = Customer::getInstance(); // Hoe kom ik hier aan een instantie van een subclass van Customer?
}
En waarom zijn "systemen met singleton zijn minder helder omdat het niet meteen duidelijk is welke dependencies een object heeft."
Ongeveer hetzelfde probleem als je hebt met globals, je weet niet wie/wat/waar en wanneer welk object aanpast zonder in de method zelf te gaan kijken. Ergo, methods kunnen onbekende bijeffecten hebben. Hoe komt de aanroeper van de buy() methode hierboven te weten wat er met z'n Customer gebeurd? Sterker nog, hoe weet 'ie dat er uberhaupt iets mee gebeurt? Met parameters is dat een heel stuk duidelijker :)

Acties:
  • 0 Henk 'm!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

PrisonerOfPain heeft de meeste punten al goed uitgelegd en verder:
Ik snap ook eerlijkgezegd niet helemaal waarom IOC voorkomt dat je singletons nodig hebt? Omdat het framework zelf ervanuit kan gaan dat er maar een instantie van, bijvoorbeeld, DomDocument bestaan? Tenminste, ik begreep uit de link die je gaf dat IOC betekend dat de controll voor bijvoorbeeld iets naar een beeldscherm brengen (realisatie van de output) verplaatst van de applicatie naar je framework.
Een IOC container zorgt voor een gemeenschappelijke context waarin objecten aangemaakt kunnen worden. Vaak kun je objecten als 'singleton' registeren, maw: het object word maar een keer aangemaakt ook al is het op meerdere plekken nodig. En dan heb je dus hetzelfde gedrag als met een singleton design pattern, maar zonder de narigheid.

Je moet een IOC container zien als een sjieke manier van object aanmaak en opslag.

Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Maar wordt dan de zelfde instantie gebruikt als je een nieuwe aan probeert te maken, of wordt een veld/attribuut gewoon automatisch gevuld met een reference naar die ene instantie? Het lijkt me dat je dan wel de mogelijkheid hebt om nieuwe instanties aan te maken en dat je gewoon gedocumenteerd moet hebben hoe je aan de instantie komt.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Michali schreef op maandag 27 maart 2006 @ 10:27:
Maar wordt dan de zelfde instantie gebruikt als je een nieuwe aan probeert te maken, of wordt een veld/attribuut gewoon automatisch gevuld met een reference naar die ene instantie? Het lijkt me dat je dan wel de mogelijkheid hebt om nieuwe instanties aan te maken en dat je gewoon gedocumenteerd moet hebben hoe je aan de instantie komt.
Je kunt het opgeven bij je bean:

vb:

code:
1
2
3
4
5
6
7
<bean id="someList1"
          class="java.util.ArrayList"
          singleton="false"/>

<bean id="someList2"
          class="java.util.ArrayList"
          singleton="true"/>


Iedere keer als someList1 wordt aangemaakt krijg je een nieuwe instantie omdat de singleton property op false staat. Iedere keer als je someList2 nodig bent krijg je gewoon dezelfde instantie terug (alle singletonbeans zijn gewoon opgeslagen in een hashtable).

[ Voor 7% gewijzigd door Alarmnummer op 27-03-2006 10:52 ]


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Ok, dan is het wel een leuk systeem. Maar is dat niet verwarrend af en toe? Je moet natuurlijk wel weten waar je mee bezig bent. Ik zie alleen niet wat het voordeel hiervan nu boven normale singletons is. Wat ik kan bedenken is dat je van classes die er niet in eerste instantie voor bestemd waren toch singletons kunt maken. En andersom, dat je classes die je normaal in singleton vorm zou gebruiken, ook in andere situaties zou kunnen gebruiken. Alleen lijkt me dat zelden voorkomen.

Dit lijkt overigens een beetje op het Monostate pattern zo. In dat pattern heeft een class gewone methods, maar die werken alleen met statische members. Zo kun je gewoon nieuwe instanties aanmaken, maar de state blijft gemeenschappelijk. De voordelen die ik hierboven noemde zijn dan natuurlijk niet van toepassing.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • -FoX-
  • Registratie: Januari 2002
  • Niet online

-FoX-

Carpe Diem!

Vaak ga je dan ook niet gewoon een arraylist al dan niet singleton maken. Een beter voorbeeld is om je business logic 'services', als singleton te gebruiken. Dit definieer je dan in je IOC container en deze zal er dan ook voor zorgen dat je service als singleton gebruikt zal worden.
Je huidige implementatie blijft er dan gewoon hetzelfde uitzien.. als een simpele class en je hoeft je verder ook niets aan te trekken van overige problemen die bij een Singleton komen kijken (concurrency issues e.d.)

Acties:
  • 0 Henk 'm!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Michali schreef op maandag 27 maart 2006 @ 11:12:
Ok, dan is het wel een leuk systeem. Maar is dat niet verwarrend af en toe? Je moet natuurlijk wel weten waar je mee bezig bent.
Persoonlijk vind ik het extreem verhelderend. Je moet wel bedenken dat je niet ieder object in je systeem op deze manier op gaat lijmen, alleen de belangrijke. Je krijgt dus een aantal bestanden waarin je hele systeem in elkaar gelijmd wordt en dat is imho extreem inzichtelijk. Verder ga je ook veel meer denken in termen van losse componenten en je hebt verder een prachtige omgeving waar je dus alles aan elkaar vast kunt lijmen.
Ik zie alleen niet wat het voordeel hiervan nu boven normale singletons is.
Zie mijn 1e reply in dit topic.
Wat ik kan bedenken is dat je van classes die er niet in eerste instantie voor bestemd waren toch singletons kunt maken. En andersom, dat je classes die je normaal in singleton vorm zou gebruiken, ook in andere situaties zou kunnen gebruiken. Alleen lijkt me dat zelden voorkomen.
Een class maak je wel klaar om in een multithreaded omgeving te kunnen gebruiken (of immutable maken, of werken met synchronisatie). Dat is de enige eis die je stelt aan zo'n object. Als aan die eis voldaan wordt, dan kan je het gewoon een singleton maken.

Veel objecten in je systeem die maak je dus zo:
Dao`s, Managers, Controllers, Schedulers, etc etc etc.
Dit lijkt overigens een beetje op het Monostate pattern zo. In dat pattern heeft een class gewone methods, maar die werken alleen met statische members.
Hmmm tja.. geef mij toch gewoon maar een normaal object en die pass ik wel rond aan iedereen die het nodig is.

Acties:
  • 0 Henk 'm!

  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 30-07 17:20

JHS

Splitting the thaum.

Topicstarter
Gezien de adviezen, zeker het wijzen op Liskov, heb ik maar besluiten het op te lossen met een Registry (achtig) pattern. De IOC containers lijken me best intressant, is er nog aanbevolen literatuur / internet daarover :) ?

PrisonerOfPain: Waar ik wel nog over viel is:
PHP:
1
2
3
4
$customer = Customer::getInstance(); // Hoe kom ik hier aan een instantie van een subclass van Customer?

/* En hoe kom ik hier aan een subclass van Customer? */
$customer = new Customer;

[ Voor 3% gewijzigd door JHS op 30-03-2006 18:22 ]

DM!


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Een class met subclasses is sowieso vaak niet geschikt voor Singleton. Althans, ik heb het nog nooit zo gebruikt. Beter is om dan gebruik te maken van een factory, los of binnen een class die alle customers beheert.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
JHS schreef op donderdag 30 maart 2006 @ 16:51:
PrisonerOfPain: Waar ik wel nog over viel is: [...]
Niet. Het argument was dan ook dat als je geen singleton gebruikt, je eerder geneigt bent om een class als parameter door te geven zodat je in de method zelf gebruik kunt maken van de subclass. Nou kun je dat nogsteeds doen met een singleton, hoor. Enkel wordt dat (vrijwel) nooit gedaan, omdat je toch overal aan een referentie kan komen.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
public function pay(Customer $c){
   $c->performAction();
}

$bank->pay(Customer::getInstance());
$bank->pay($this->customer_); // Passing references like we used to

public function pay(){
   $c = Customer::getInstance();
   $c->performAction();
}

$bank->pay(); // Pay what, to whom, what if we have an ValuedCustomer?

Het gedrag van het laatste voorbeeld, word door een singleton in de hand gewerkt, en kan in een hoop situaties een serieus nadeel zijn waar je pas laat achter komt.

[ Voor 3% gewijzigd door PrisonerOfPain op 30-03-2006 21:05 ]


Acties:
  • 0 Henk 'm!

  • JHS
  • Registratie: Augustus 2003
  • Laatst online: 30-07 17:20

JHS

Splitting the thaum.

Topicstarter
Ah, oké, nu volg ik het een stuk beter :) . Ik ga 'er maar nog wat meer over nadenken..

DM!


Acties:
  • 0 Henk 'm!

  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 03-08 23:13

reddog33hummer

Dat schept mogelijkheden

Wat meestal een makkelijke manier is om een extendable singleton te maken is een abstracte classe die protected instance variable heeft. Deze kan je dan tijdens de start van het programma instancieren met het soort singleton wat je nodig hebt. Dit werkt heel handig voor programma's die onder DotNET (JSharp) en Sun JVM moeten draaien. Je kan dan singletons voor fileacties uitwissselen (zijn dan abstract).

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public abstract class MasterSingleton
{
 protected static MasterSingleton instance = null;

 protected MasterSingleton(){
   instance = this;
 }
 
 public static final MasterSingleton getInstance(){
   if(instance == null)
   {
     throw new RuntimeException("Instance not instanciated");
   }
   return instance;
 }

 public abstract void destory(); //Voor veranderbaare singleton (zoals state patern)
}

public class SlaveSingleton extends MasterSingleton
{
   protected SlaveSingleton(){
      super();
   }

   public static void createInstance(){
      if(instance == null){
         new SlaveSingleton();
      }
      else //Singleton die je kan veranderen, meer als state pattern
      {
         instance.destroy(); //moet je wel in master defineren als abstract method        
         new SlaveSingleton();
      }
   }
}

[ Voor 5% gewijzigd door reddog33hummer op 31-03-2006 09:00 . Reden: Kan niet in 1 keer proggen ]

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


Acties:
  • 0 Henk 'm!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Deze constructie is volgens mij niet echt threadsafe. Heb je daar nog geen issues mee gehad?

Acties:
  • 0 Henk 'm!

  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 03-08 23:13

reddog33hummer

Dat schept mogelijkheden

Op deze manier is hij inderdaad niet threadsafe. Maar das meestal ook niet erg. Je kan de destroy weglaten en gewoon door de garbage collector laten doen. Dan is hij zoizo threadsafe.
Omdat het unsafe gedeelte hier zit
code:
1
2
         instance.destroy(); //moet je wel in master defineren als abstract method        
         new SlaveSingleton();

Als je de destory weg laat werkt de oude singleton de nog aanwezige afhandelingen af.
Je moet de destory dan ok meer als notify zien, dat hij klaar moet gaan om afgemaakt te worden.
Je kan daardom ook:
code:
1
2
3
         MasterSingleton old = instance;
         new SlaveSingleton();
         old.destory();

doen. Maar dan zit je nog met hetzelfde probleem. Je kan locks gaan introduceren, maar singletons worden meestal door het hele programma gebruikt en dat brengt meestal je programma tot stilstand.
Makkelijker is het dan om er gewoon rekening mee te houden en de destroy te scedulen.

[ Voor 37% gewijzigd door reddog33hummer op 31-03-2006 10:04 ]

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

Alarmnummer schreef op vrijdag 31 maart 2006 @ 09:27:
Deze constructie is volgens mij niet echt threadsafe. Heb je daar nog geen issues mee gehad?
getInstance en createInstance synchronized maken zou genoeg moeten zijn om het wel thread safe te maken op het eerste gezicht. ;) sowieso slim bij een singleton klasse

Fat Pizza's pizza, they are big and they are cheezy


Acties:
  • 0 Henk 'm!

  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 03-08 23:13

reddog33hummer

Dat schept mogelijkheden

JKVA schreef op vrijdag 31 maart 2006 @ 10:01:
getInstance en createInstance synchronized maken zou genoeg moeten zijn om het wel thread safe te maken op het eerste gezicht. ;) sowieso slim bij een singleton klasse
Dan heb je nog steeds het probleem met de destory.
code:
1
2
3
4
thread 1: MasterSingleton one = getInstance();
thread 2: AppelSingleton.createInstance();
thread 2: instance.destory();
thread 1: one.doeActie (); // oeps, bestaat al niet meer

Tenzij je deze doet
code:
1
2
3
         MasterSingleton old = instance;
         new SlaveSingleton();
         old.destory();

Hoe er dan wel rekening mee dat je nog een static object moet hebben om een lock te crieeren, omdat de nieuwe SlaveSingleton niet dezelfde classe is.
code:
1
2
3
4
thread 1: PeerSingleton.createInstance(); //lock in de peerSingleton
thread 2: AppelSingleton.createInstance(); //lock in de AppleSingleton dus niet gelockt
thread 1: old.destory();
thread 2: old.destory(); //en toen waren ze beide weg

Verstandigger is het om geen destory te gebruiken en/of hem te scedgulen.
Als je dat doet, hoef je geen synchronized te gebruiken omdat de functie instance = this atoomair is.
Dat scheelt enorm in preformance.
het wordt dan:
code:
1
2
3
public static void createInstance(){
    new SlaveSingleton();
}

[ Voor 51% gewijzigd door reddog33hummer op 31-03-2006 10:22 ]

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

reddog33hummer schreef op vrijdag 31 maart 2006 @ 10:07:
[...]
Dan heb je nog steeds het probleem met de destory.
[...]
Die snap ik niet. :? In Java heb je hier naar mijn idee nooit mee te maken, aangezien je geen destroy hebt. Ik weet niet hoe het met andere talen zit, maar iets static mag je naar mijn idee niet destroyen. Komt een beetje overeen met het deleten van een class file. :P

Maar serieus, kun je die destroy dan niet overriden ofzo, zodat je een singleton niet kan deleten?

Fat Pizza's pizza, they are big and they are cheezy


Acties:
  • 0 Henk 'm!

  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 03-08 23:13

reddog33hummer

Dat schept mogelijkheden

JKVA schreef op zondag 02 april 2006 @ 11:07:
[...]


Die snap ik niet. :? In Java heb je hier naar mijn idee nooit mee te maken, aangezien je geen destroy hebt. Ik weet niet hoe het met andere talen zit, maar iets static mag je naar mijn idee niet destroyen. Komt een beetje overeen met het deleten van een class file. :P

Maar serieus, kun je die destroy dan niet overriden ofzo, zodat je een singleton niet kan deleten?
Je moet niet letterlijk destory lezen.
Stel je voor dat dit een logger is die een file open heeft staan.
Bij de destroy sluit hij de file.

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Hier trouwens een blogpost van Jon Skeet over singletons en inheritance.
Ook hij vind dat dit niet kan, tenzij je nested types laat inheriten.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik vond het ook wat kort door de bocht. Een singleton wil zeggen dat je van een type maar 1 instantie mag hebben, het zegt natuurlijk niets over een mogelijke afgeleide class van die singeton. Als er echter een afgeleide klasse van bestaat, impliceert dat wel dat die afgeleide klasse automatisch óók een singleton is, en dat de instance van de afgeleide dezelfde is als die van de base (anders heb je immers meerdere bases, en dat mag niet want het is nou juist een singleton)

Zo hebben wij een generieke RenderDevice interface voor onze cross-platform games, met PC, Xbox, Xbox360, PS2, etc. implementaties daarvan. Een gederivieerde interface kan echter wel functionaliteit toevoegen dat specifiek voor dat platform is. De instance member van RenderDevice wijst dan ook naar hetzelfde object als de instance member van de XenonRenderDevice, op het moment dat die aangemaakt is.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Waar ik net aan dacht is dit: iedere taal heeft toch wel de mogelijkheid om te serializen? In princiepe, als je zou willen, zou je dan altijd aan een nieuwe instance kunnen komen. Niet dat je je er echt druk om moet maken ofzo, maar 100% afschermen lukt je toch nooit.

Met de runkit extensie in PHP kun je methods ook herdefineren, dan je kun je de constructor zo public maken.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, niet alle objecten zijn te serializen, volgens mij kom je sowieso in de problemen op het moment dat de constructor niet public is. Dat je er met wat hackery wel bij kan is natuurlijk geen argument om dan maar helemaal geen singleton enforcement toe te passen.

Het hele voordeel van een singleton is juist dat je altijd met 1 object werkt die globaal te accessen is, zodat je niet overal nutteloze referenties mee hoeft te geven aan allerlei instanties. Dus waarom zou je zelfs willen om meerdere instanties van die class te maken? De maker van de singleton zorgt er gewoon voor dat hij maar 1 instantie maakt die opvraagbaar is, dat anderen daar vervolgens met wat hacks meerdere instanties van weten te maken, so be it. Maar dan kan die persoon tevens ook niet verwachten dat het allemaal maar vlekkeloos werkt.

[ Voor 56% gewijzigd door .oisyn op 02-05-2006 12:07 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Daar heb je ook helemaal gelijk in. Ik wilde geen punt maken dat een Singleton overbodig is, gewoon iets waar ik aan dacht. Ik was meer benieuwd naar methoden om een Singleton te kraken :P

Noushka's Magnificent Dream | Unity

Pagina: 1