In dit artikel gaat u leren hoe u het Singleton-ontwerppatroon implementeert en waarom en wanneer u dit patroon in uw toepassing moet gebruiken. Zoals de naam "Singleton" suggereert, kunnen we met deze methode één en slechts één object van een klasse maken.
Laten we eens kijken wat we op Wikipedia hebben over dit ontwerppatroon:
Het singleton-patroon is een ontwerppatroon dat de instantiatie van een klasse beperkt tot één object. Dit is handig als precies één object nodig is om acties in het hele systeem te coördineren.
Zoals in de bovenstaande definitie wordt vermeld, moeten we het Singleton-patroon voor die klasse implementeren als we ervoor willen zorgen dat voor elke klasse één en slechts één object moet worden gemaakt..
Je zou je kunnen afvragen waarom we zo'n klasse zouden moeten implementeren, waardoor we maar één object ervan kunnen maken. Ik zou zeggen dat er veel gevallen zijn waarin we dit ontwerppatroon kunnen toepassen. Deze omvatten: configuratieklasse, sessieklasse, databaseklasse en nog veel meer.
Ik neem het voorbeeld van een database-klasse voor dit artikel. Eerst zullen we zien wat het probleem kan zijn als een Singleton-patroon niet voor een dergelijke klasse is geïmplementeerd.
Stel je een heel eenvoudige databaseverbindingsklasse voor die een verbinding met de database maakt zodra we een object van die klasse maken.
class database private $ dbName = null, $ dbHost = null, $ dbPass = null, $ dbUser = null; public function __construct ($ dbDetails = array ()) $ this-> dbName = $ dbDetails ['db_name']; $ this-> dbHost = $ dbDetails ['db_host']; $ this-> dbUser = $ dbDetails ['db_user']; $ this-> dbPass = $ dbDetails ['db_pass']; $ this-> dbh = nieuwe PDO ('mysql: host ='. $ this-> dbHost. '; dbname ='. $ this-> dbName, $ this-> dbUser, $ this-> dbPass);
In het bovenstaande codevoorbeeld ziet u dat het elke keer dat u een object van deze klasse maakt een verbinding met de database maakt. Dus als een ontwikkelaar op meerdere plaatsen een object van deze klasse heeft gemaakt, stel je het aantal (identieke) databaseverbindingen voor dat het met de databaseserver maakt..
Dus zonder het te weten maakt de ontwikkelaar fouten die een enorme impact hebben op de snelheid van de database en de applicatieserver. Laten we hetzelfde zien door een ander object van die klasse te maken.
$ dbDetails = array ('db_name' => 'designpatterns', 'db_host' => 'localhost', 'db_user' => 'root', 'db_pass' => 'mysqldba'); $ db1 = nieuwe database ($ dbDetails); var_dump ($ db1); $ db2 = nieuwe database ($ dbDetails); var_dump ($ db2); $ db3 = nieuwe database ($ dbDetails); var_dump ($ db3); $ db4 = nieuwe database ($ dbDetails); var_dump ($ DB4); // Output object (database) [1] private 'dbName' => string 'designpatterns' (length = 14) private 'dbHost' => string 'localhost' (length = 9) private 'dbPass' => string 'mysqldba' (length = 8) private 'dbUser' => string 'root' (length = 4) public 'dbh' => object (PDO) [2] object (database) [3] private 'dbName' => string 'designpatterns' (lengte = 14) private 'dbHost' => string 'localhost' (lengte = 9) private 'dbPass' => string 'mysqldba' (length = 8) private 'dbUser' => string 'root' (lengte = 4) public 'dbh' => object (PDO) [4] object (database) [5] private 'dbName' => string 'designpatterns' (length = 14) private 'dbHost' => string 'localhost' (lengte = 9) private 'dbPass' => string 'mysqldba' (length = 8) private 'dbUser' => string 'root' (length = 4) public 'dbh' => object (PDO) [6] object (database) [7] private 'dbName' => string 'designpatterns' (length = 14) private 'dbHost' => string 'localhost' (lengte = 9) private 'dbPass' => string 'mysqldba' (length = 8) private 'dbUser' = > string 'root' (length = 4) public 'dbh' => o bject (BOB) [8]
Als u de uitvoer van de bovenstaande code en uitvoer ziet, kunt u zien dat aan elk object een nieuwe resource-ID is toegewezen, dus alle objecten zijn volledig nieuw en daarom wijst het ook afzonderlijk geheugen toe. Dus onbewust bezet onze applicatie middelen die echt niet nodig zijn.
Het is niet onze beslissing hoe ontwikkelaars ons basisraamwerk gebruiken. Het is in onze controle nadat het codebeoordelingsproces plaatsvindt, maar tijdens de ontwikkeling kunnen we niet altijd achter hen staan.
Om een dergelijke situatie te overwinnen, moeten we onze basisklasse op zo'n manier maken dat het niet in staat is om meerdere objecten van een klasse te maken; in plaats daarvan geeft het een reeds gemaakt object als dat er al is. Dit is het geval waar we zouden moeten overwegen om een Singleton-patroon te ontwikkelen voor onze basisklassen.
Bij het implementeren van dit patroon, is ons doel om het maken van een object van een klasse één en slechts één keer mogelijk te maken. Sta mij toe om de onderstaande klassencode toe te voegen en dan gaan we door elk deel van deze klasse.
class database private $ dbName = null, $ dbHost = null, $ dbPass = null, $ dbUser = null; privé static $ instance = null; private function __construct ($ dbDetails = array ()) // Let op: dit is Private Constructor $ this-> dbName = $ dbDetails ['db_name']; $ this-> dbHost = $ dbDetails ['db_host']; $ this-> dbUser = $ dbDetails ['db_user']; $ this-> dbPass = $ dbDetails ['db_pass']; // Uw code hier om verbinding te maken met de database // $ this-> dbh = nieuwe PDO ('mysql: host ='. $ This-> dbHost. '; Dbname ='. $ This-> dbName, $ this-> dbUser , $ dit-> dbPass); public static function connect ($ dbDetails = array ()) // Controleer of instantie al bestaat als (self :: $ instance == null) self :: $ instance = nieuwe database ($ dbDetails); return self :: $ instance; persoonlijke functie __clone () // Cloningfunctie stopzetten privéfunctie __wakeup () // Anserialisatie van object stoppen
Er is weinig indicatie dat de bovenstaande klasse een Singleton-klas is. Het allereerste is een particuliere constructor, die het maken van objecten met het nieuwe sleutelwoord voorkomt. Een andere indicatie is één statische ledvariabele die de verwijzing naar een reeds gemaakt object bevat.
$ dbDetails = array ('db_name' => 'designpatterns', 'db_host' => 'localhost', 'db_user' => 'root', 'db_pass' => 'mysqldba'); $ db1 = database :: connect ($ dbDetails); var_dump ($ db1); $ db2 = database :: connect ($ dbDetails); var_dump ($ db2); $ db3 = database :: connect ($ dbDetails); var_dump ($ db3); $ db4 = database :: connect ($ dbDetails); var_dump ($ DB4); // Output object (database) [1] private 'dbName' => string 'designpatterns' (length = 14) private 'dbHost' => string 'localhost' (length = 9) private 'dbPass' => string 'mysqldba' (length = 8) private 'dbUser' => string 'root' (length = 4) public 'dbh' => object (PDO) [2] object (database) [1] private 'dbName' => string 'designpatterns' (lengte = 14) private 'dbHost' => string 'localhost' (lengte = 9) private 'dbPass' => string 'mysqldba' (length = 8) private 'dbUser' => string 'root' (lengte = 4) public 'dbh' => object (PDO) [2] object (database) [1] private 'dbName' => string 'designpatterns' (length = 14) private 'dbHost' => string 'localhost' (lengte = 9) private 'dbPass' => string 'mysqldba' (length = 8) private 'dbUser' => string 'root' (length = 4) public 'dbh' => object (PDO) [2] object (database) [1] private 'dbName' => string 'designpatterns' (length = 14) private 'dbHost' => string 'localhost' (lengte = 9) private 'dbPass' => string 'mysqldba' (length = 8) private 'dbUser' = > string 'root' (length = 4) public 'dbh' => o bject (BOB) [2]
Als u de uitvoer van beide secties vergelijkt, ziet u dat in de uitvoer van het Singleton-patroon de resource-ID voor het object hetzelfde is voor alle verschillende objecten. Maar dat is niet het geval wanneer het ontwerppatroon niet wordt gebruikt.
Dit ontwerppatroon wordt ook wel een anti-patroon genoemd om verschillende redenen, die ik hieronder zal noemen:
Ik heb mijn best gedaan het Singleton-ontwerppatroon, dat veel wordt besproken op internet, uit te leggen. Ik hoop dat je dit artikel nuttig vindt. We hebben beide aspecten van dit patroon besproken, die als een ontwerppatroon en als antipatroon zijn.
Plaats hieronder uw opmerkingen, suggesties en / of vragen en ik zal mijn reactie zo snel mogelijk posten. Je kunt me ook bereiken op Twitter @XpertDevelopers of me meteen een e-mail sturen.