Aller au contenu principal

Les design patterns

Notions théoriques

Un design pattern (patron de conception en français) est une solution générale réutilisable à un problème qui se produit fréquemment dans la conception logicielle.

attention

Les designs design patterns ne sont pas des modèles de conception que vous pouvez transformer directement en code, mais plutôt des descriptions de problèmes et de solutions qui peuvent être utilisées dans de nombreux contextes différents.

Voici trois des design patterns les plus couramment utilisés :

  1. Singleton : Ce design pattern assure qu'une classe n'a qu'une seule instance et fournit un point d'accès global à cette instance.

  2. Factory : Ce design pattern permet de créer des objets sans spécifier la classe exacte à utiliser. La classe Factory décide quelle sous-classe créer.

  3. Observer : Ce design pattern permet à un objet (l'observateur) de surveiller les changements dans un autre objet (le sujet). L'objet observateur est notifié lorsque l'état du sujet change.

Exemple pratique

1) Le design pattern Factory

Dans notre jeu de combat, nous pourrions par exemple utiliser le design pattern Factory pour créer nos personnages.

Voici comment cela pourrait se présenter :

class CharacterFactory {
public static function create($type) {
switch ($type) {
case 'guerrier':
return new Warrior();
case 'mage':
return new Mage();
default:
throw new Exception("Type de personnage inconnu : $type");
}
}
}

Et voici comment vous pourriez l'utiliser pour créer un personnage de type Warrior (Guerrier en anglais) :

$character = CharacterFactory::create('guerrier');

2) Le design pattern Singleton

Dans notre jeu de combat, nous pourrions par exemple utiliser le design pattern Singleton pour représenter le monde du jeu, qui doit être unique.

Voici comment cela pourrait se présenter :

class GameConfig {
private static $instance;
private $maxPlayers;
private $gameDuration;

private function __construct() {
// Constructeur privé pour empêcher la création directe d'objets
$this->maxPlayers = 4;
$this->gameDuration = 60; // en minutes
}

public static function getInstance() {
if (null === self::$instance) {
self::$instance = new self();
}

return self::$instance;
}

public function getMaxPlayers() {
return $this->maxPlayers;
}

public function getGameDuration() {
return $this->gameDuration;
}
}

Et voici comment vous pourriez l'utiliser pour obtenir l'unique instance de la configuration du jeu :

$config = GameConfig::getInstance();

echo "Nombre maximum de joueurs : " . $config->getMaxPlayers() . "\n";
echo "Durée d'une partie : " . $config->getGameDuration() . " minutes\n";

Cet exemple crée une seule instance de GameConfig.

$config2 = GameConfig::getInstance();

$config2 contient la même instance de GameConfig que $config.

Test de mémorisation/compréhension


Qu'est-ce qu'un design pattern ?


Que fait le design pattern Singleton ?


Que fait le design pattern Factory ?


Que fait le design pattern Observer ?


Pourquoi utilise t'on des design patterns ?



TP pour réfléchir et résoudre des problèmes

Voici un TP où nous allons créer une classe Singleton pour gérer une connexion à une base de données.

Réutilisation de la connexion

Lorsque vous utilisez le Singleton pour gérer une connexion à la base de données, vous créez une seule instance de la connexion qui est réutilisée tout au long de l'application.

Cela signifie que vous n'ouvrez pas plusieurs connexions à chaque fois que vous avez besoin d'accéder à la base de données, ce qui peut être coûteux en termes de ressources.

Consignes du TP :

  1. Créez un dossier tp-singleton dans votre dossier Documents.

  2. Dans votre dossier tp-singleton, créez un fichier DatabaseConnection.php pour la nouvelle classe DatabaseConnection avec les propriétés privées suivantes : $instance, $hostname, $username, $password et $database.

  3. Le constructeur de cette classe doit être privé et initialiser les propriétés $hostname, $username, $password et $database avec des valeurs par défaut.

    • hostname : 'localhost'
    • username : 'root'
    • password : 'root'
    • database : 'test_db'
  4. Ajoutez une méthode publique statique getInstance().

    Cette méthode doit vérifier si $instance est null. Si c'est le cas, elle doit créer une nouvelle instance de DatabaseConnection et l'affecter à $instance. Ensuite, elle doit retourner $instance. Assurez-vous d'utiliser self pour faire référence à la classe actuelle.

  5. Ajoutez une méthode publique connect(). Cette méthode doit essayer d'établir une connexion à la base de données en utilisant les informations de connexion stockées dans les propriétés de l'objet.

    Si la connexion échoue, elle doit lancer une exception.

        public function connect() {
    $conn = new mysqli($this->hostname, $this->username, $this->password, $this->database);

    if ($conn->connect_error) {
    throw new Exception("Connection failed: " . $conn->connect_error);
    }

    echo "Connected successfully";
    }


6. Créez un fichier `main.php` pour tester votre classe `DatabaseConnection`.
> Dans ce fichier, mettez en place un bloc `try/catch` pour attraper toute exception qui pourrait être lancée lors de la tentative de connexion à la base de données.
```php
try {
$db = DatabaseConnection::getInstance();
$db->connect();
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
  1. Exécutez votre programme :
php main.php
Une solution