Hello, fellow developers!π§πΌβπ»
In the previous article, I showed examples of implementing the design patterns Singleton and Multiton using inheritance. This is a fairly convenient approach, provided that we have several simple classes in the project that implement just a few methods and require a single instance in all places where these methods are called.
The php language only allows single inheritance, and this may be the reason why the variant from the last article will complicate or even break the architecture of our application. Therefore, I propose to consider other options for implementing the patterns.
Often, the correct solution is to implement the pattern in every class that requires it.
class Database
{
private static self|null $instance = null;
final private function __construct(){}
final private function __clone(){}
final private function __wakeup(){}
public static function getInstance(): self
{
if (self::$instance === null) {
self::$instance = new self;
}
return self::$instance;
}
public function connect()
{
// ...
}
}
$db = Database::getInstance();
$db->connect();
An alternative would be to use traits. This option is suitable if the project has several classes and you want to extract part of the repeating code in order to comply with the DRY principle.
trait MultitonTrait
{
private static array|null $instance = null;
public static function getInstance(int|string $key): self
{
if (!array_key_exists($key, self::$instance)) {
self::$instance[$key] = new self;
}
return self::$instance[$key];
}
}
class Database
{
use MultitonTrait;
final private function __construct(){}
final private function __clone(){}
final private function __wakeup(){}
public function connect()
{
// ...
}
}
$db = Database::getInstance('mysql');
$db->connect();
All options from this article and the previous one have both their pros and cons, so the best solution should be chosen based on the architecture of a particular project.
P.S. Fellow developers, if you've found value in this article and are eager to deepen your understanding of design patterns in PHP and TypeScript, I have thrilling news for you! I am in the midst of crafting a comprehensive book that delves extensively into these topics, filled with practical examples, lucid explanations, and real-world applications of these patterns.
This book is being designed to cater to both novices and seasoned developers, aiming to bolster your understanding and implementation of design patterns in PHP and TypeScript. Whether you are aiming to refresh your existing knowledge or venture into new learning territories, this book is your perfect companion.
Moreover, your subscription will play a pivotal role in supporting the completion of this book, enabling me to continue providing you with quality content that can elevate your coding prowess to unprecedented heights.
I invite you to subscribe to my blog on dev.to for regular updates. I am eager to embark on this journey with you, helping you to escalate your coding skills to the next level!
Top comments (4)
Traits are maybe helpful to not repeat code parts in a project, but it can easily prevent you to follow other interesting patterns like "Composition Over Inheritance" or "KISS" or "Open/Closed" because a trait in PHP is more or less code that will be copied into the class on runtime. The problem will only come up if you over-use traits or if you extend a class with traits, a quick solution would be to use an interface for every trait: e.g.: 3v4l.org/CfuF7#v8.1.8
Some hints for your code example:
e.g.
array_key_exists
will throw a warning on the first run because NULL is the default value for the static property "instance". You could just use an empty array as default so that you do not need to handle the NULL type.PS: I already wrote that on my last comment ;) but I think it's important to know if someone is starting using Singleton Patterns -> you maybe do not need this at all because you can move this decision into your container e.g.: container.thephpleague.com/4.x/def...
Here is also an interesting article about php traits: matthiasnoback.nl/2022/07/when-to-...
Or you could let go of the Singleton anti pattern and use a proper registry β¦
Interesting.