Add interfaces and traits for registries

1.x 1.3.0
Julien Rosset 3 years ago
parent 65e6d0a898
commit 6bf4ea2131

@ -0,0 +1,47 @@
<?php
namespace jrosset\Singleton;
use InvalidArgumentException;
use Throwable;
/**
* Interface for class implementing an instance register
*
* @see TRegistry for default implementation
*/
interface IRegistry {
/**
* Register a new entry
*
* @param string $name The entry name
* @param array $args The instance constructor arguments
*
* @return void
*
* @throws InvalidArgumentException If the entry name already exists
*/
public static function addEntry (string $name, ...$args): void;
/**
* Check if an entry name already exists
*
* @param string $name The entry name
*
* @return bool TRUE if the entry name already exists
*/
public static function hasEntry (string $name): bool;
/**
* Get the instance
*
* If the instance is not already created then create it
*
* @param string The entry name
*
* @return static The instance
*
* @throws InvalidArgumentException If the entry name doesn't exist
* @throws Throwable If instantiating failed
*/
public static function getInstance (string $name): self;
}

@ -0,0 +1,40 @@
<?php
namespace jrosset\Singleton;
use InvalidArgumentException;
use Throwable;
/**
* Interface for class implementing an instance register with a default entry name
*/
interface IRegistryDefault extends IRegistry {
/**
* The default entry name
*
* @return string The default entry name
*
* @throws InvalidArgumentException If the entry name isn't set
*/
public static function getDefaultEntryName (): string;
/**
* Set the default entry name
*
* <b>WARNING :</b> The entry name MUST already exists
*
* @param string $name The new default name
*
* @return void
*
* @throws InvalidArgumentException If the entry name doesn't exists
*/
public static function setDefaultEntryName (string $name): void;
/**
* @inheritDoc
*
* @throws InvalidArgumentException If the entry name doesn't exist or no default entry name
* @throws Throwable If instantiating failed
*/
public static function getInstance (?string $name = null): self;
}

@ -3,7 +3,9 @@
namespace jrosset\Singleton;
/**
* Interface for class that must implements a singleton
* Interface for class implementing a singleton
*
* @see TSingleton for common implementation
*/
interface ISingleton {
/**

@ -0,0 +1,21 @@
<?php
namespace jrosset\Singleton;
/**
* Default implementation for registry
*
* Instance initialization through the constructor
*
* @see IRegistry for interface
*/
trait TRegistry {
use TRegistryBase;
/**
* @inheritDoc
*/
public static function getInstance (string $name): self {
return static::TRegistryBase_getInstance($name);
}
}

@ -0,0 +1,62 @@
<?php
namespace jrosset\Singleton;
use InvalidArgumentException;
use Throwable;
/**
* Default base implementation for registry
*
* Instance initialization through the constructor
*
* @see IRegistry for interface
*/
trait TRegistryBase {
/**
* @var array[] The registry entries
*/
private static array $registerEntries = [];
/**
* @var static[] The current instances
*/
private static array $registryInstances = [];
/**
* @inheritDoc
*/
public static function addEntry (string $name, ...$args): void {
if (static::hasEntry($name)) {
throw new InvalidArgumentException('An entry with "' . $name . '" already exists');
}
static::$registerEntries[$name] = $args;
}
/**
* @inheritDoc
*/
public static function hasEntry (string $name): bool {
return isset(static::$registerEntries[$name]);
}
/**
* Get the instance
*
* If the instance is not already created then create it
*
* @param string The entry name
*
* @return static The instance
*
* @throws InvalidArgumentException If the entry name doesn't exist
* @throws Throwable If instantiating failed
*/
public static function TRegistryBase_getInstance (string $name): self {
if (!static::hasEntry($name)) {
throw new InvalidArgumentException('Unable to find entry "' . $name . '"');
}
if (!isset(static::$registryInstances[$name])) {
static::$registryInstances[$name] = new static(...static::$registerEntries[$name]);
}
return static::$registryInstances[$name];
}
}

@ -0,0 +1,44 @@
<?php
namespace jrosset\Singleton;
use InvalidArgumentException;
/**
* Default implementation for registry with default entry name
*
* Instance initialization through the constructor
*
* @see IRegistryDefault for interface
*/
trait TRegistryDefault {
use TRegistryBase;
/**
* @var string|null The default entry name. NULL if not defined yet
*/
private static ?string $registryDefaultEntryName = null;
/**
* @inheritDoc
*/
public static function getDefaultEntryName (): string {
if (static::$registryDefaultEntryName === null) {
throw new InvalidArgumentException('No default entry name set');
}
return static::$registryDefaultEntryName;
}
/**
* @inheritDoc
*/
public static function setDefaultEntryName (string $name): void {
static::$registryDefaultEntryName = $name;
}
/**
* @inheritDoc
*/
public static function getInstance (?string $name = null): self {
return static::TRegistryBase_getInstance($name ?? static::getDefaultEntryName());
}
}

@ -3,16 +3,18 @@
namespace jrosset\Singleton;
/**
* Trait for simple singleton
* Default implementation for singleton
*
* Initialization through the constructor
*
* @see ISingleton for interface
*/
trait TSingleton {
/**
* @var static|null The current instance. Null if not already created
* @noinspection PhpDocFieldTypeMismatchInspection
*/
private static ?self $singleton_instance;
private static ?self $singletonInstance;
/**
* Initialize the instance
@ -21,17 +23,13 @@ trait TSingleton {
}
/**
* Get the instance
*
* If the instance is not already created then create it
*
* @return static The instance
* @inheritDoc
*/
public static final function getInstance (): self {
if (!isset(self::$singleton_instance)) {
self::$singleton_instance = new static();
if (!isset(self::$singletonInstance)) {
self::$singletonInstance = new static();
}
return self::$singleton_instance;
return self::$singletonInstance;
}
}

@ -0,0 +1,38 @@
<?php
/** @noinspection PhpUnhandledExceptionInspection */
/** @noinspection PhpIllegalPsrClassPathInspection */
use jrosset\Singleton\IRegistry;
use jrosset\Singleton\TRegistry;
require_once __DIR__ . '/../vendor/autoload.php';
class RegistryTest implements IRegistry {
use TRegistry;
private int $cpt;
private function __construct (int $cpt) {
$this->cpt = $cpt;
}
public function getCpt (): int {
return $this->cpt;
}
public function increment (): void {
$this->cpt++;
}
}
RegistryTest::addEntry('cpt_1', 0);
RegistryTest::addEntry('cpt_2', 5);
var_dump(RegistryTest::getInstance('cpt_1')->getCpt());
var_dump(RegistryTest::getInstance('cpt_2')->getCpt());
RegistryTest::getInstance('cpt_1')->increment();
RegistryTest::getInstance('cpt_2')->increment();
var_dump(RegistryTest::getInstance('cpt_1')->getCpt());
var_dump(RegistryTest::getInstance('cpt_2')->getCpt());

@ -0,0 +1,39 @@
<?php
/** @noinspection PhpUnhandledExceptionInspection */
/** @noinspection PhpIllegalPsrClassPathInspection */
use jrosset\Singleton\IRegistryDefault;
use jrosset\Singleton\TRegistryDefault;
require_once __DIR__ . '/../vendor/autoload.php';
class RegistryDefaultTest implements IRegistryDefault {
use TRegistryDefault;
private int $cpt;
private function __construct (int $cpt) {
$this->cpt = $cpt;
}
public function getCpt (): int {
return $this->cpt;
}
public function increment (): void {
$this->cpt++;
}
}
RegistryDefaultTest::addEntry('cpt_1', -5);
RegistryDefaultTest::addEntry('cpt_2', 12);
RegistryDefaultTest::setDefaultEntryName('cpt_1');
var_dump(RegistryDefaultTest::getInstance()->getCpt());
var_dump(RegistryDefaultTest::getInstance('cpt_2')->getCpt());
RegistryDefaultTest::getInstance()->increment();
RegistryDefaultTest::getInstance('cpt_2')->increment();
var_dump(RegistryDefaultTest::getInstance()->getCpt());
var_dump(RegistryDefaultTest::getInstance('cpt_2')->getCpt());

@ -6,10 +6,14 @@ require_once __DIR__ . '/../vendor/autoload.php';
use jrosset\Singleton\ISingleton;
use jrosset\Singleton\TSingleton;
class Test implements ISingleton {
class SingletonTest implements ISingleton {
use TSingleton;
private int $cpt = 0;
private int $cpt;
private function __construct () {
$this->cpt = 0;
}
public function getCpt (): int {
return $this->cpt;
@ -19,6 +23,6 @@ class Test implements ISingleton {
}
}
var_dump(Test::getInstance()->getCpt());
Test::getInstance()->increment();
var_dump(Test::getInstance()->getCpt());
var_dump(SingletonTest::getInstance()->getCpt());
SingletonTest::getInstance()->increment();
var_dump(SingletonTest::getInstance()->getCpt());
Loading…
Cancel
Save