2017-08-30 24 views
-1

Ich möchte eine zustandslose Klasse entwerfen, die dieselbe Instanz an mehreren Stellen der Anwendung ohne Nebeneffekt wiederverwendet. Dies ist erforderlich, da viele Container für Abhängigkeitsinjektionen immer die gleiche Instanz der Klasse zurückgeben.PHP - Entwerfen einer zustandslosen Klasse

Nehmen wir an, wir haben die DirectoryUtils Klasse:

<?php 

class DirectoryUtils{ 

    private $dir; 

    public function __constructor($dir){ 
    if($this->checkDirectory($dir)){ 
     $this->dir = $dir; 
    }else{ 
     throw new Exception("Invalid Directory"); 
    } 
    } 

    public function deleteAllFiles(){ 
    // code to delete all files in $this->dir; 
    } 

    public function renameDirectory($newName){ 
    // code to rename $this->dir name to $newName 
    } 

    private function checkDirectory($dir){ 
    // check if directory exists, is writable... 
    } 

} 

Eine einzige Instanz dieser Klasse ist unbequem wiederzuverwenden. Wie man es staatenlos macht?

+2

StateLess == Keine Ahnung, was vorher passiert ist. – RiggsFolly

+1

10 * Dies ist notwendig, weil viele Dependency-Injection-Container immer dieselbe Instanz der Klasse * zurückgeben - viele davon erlauben es Ihnen auch, dies zu umgehen. Welche hast du probiert? – iainn

+0

@ainn PHP-DI wird den Prototypbereich in der nächsten Hauptversion entfernen. – Bob

Antwort

0

Ich glaube, Sie den Umfang erweitern, müssen Sie untersuchen hier: Was ist ein sinnvoller Service, den Sie im DI-Container zur Wiederverwendung setzen können?

Das Problem mit Ihrer Klasse ist nicht, dass es Stateful ist, aber dass sein Name ein Missverständnis seines Zwecks widerspiegelt. Diese Klasse stellt ein spezifisches Verzeichnis dar, sollte also entsprechend benannt werden, z.

$my_home_dir = new Directory('/home/imsop'); 
$your_home_dir = new Directory('/home/abskmj'); 
$diff_tool->compareDirs($my_home_dir, $your_home_dir); 

In Ihrem DI-Container, würden Sie dann mehrere spezifische Instanzen dieser Klasse setzen, für die spezifischen Verzeichnisse zugreifen müssen, beispielsweise

[ 
    'CacheDir' => function($config) { 
     return new Directory($config['cache_path']); 
    }, 
    'LogDir' => function($config) { 
     return new Directory($config['log_path']); 
    } 
] 

Eine andere Art von Service, den Sie schaffen könnte, ist eine Fabrik, die einen Teil des Dateisystems abstrahiert, und gibt Ihnen verschiedene Directory Objekte, zB:

$my_home_dir = $factory->getHomeDir('imsop'); 

Hier wird der Zustand konstruiert die DI könnte ein Basisverzeichnis sein in Arbeit:

[ 
    'DirectoryFactory' => function($config) { 
     return new DirectoryFactory($config['base_dir_path']); 
    } 
] 

Keines dieser Klassen ist „staatenlos“, aber beide sind unveränderlich - einmal erstellt, ändern Sie sie nicht so, dass sie auf ein anderes Verzeichnis zeigen, Sie verwenden für jeden Zweck eine andere Instanz.

Die Klasse DirectoryFactory könnte tatsächlich zustandslos sein, wenn die gesamte Logik fest codiert wäre (z. B. "ein Basisverzeichnis ist immer '/home/' . $user_name").Dies könnte immer noch nützlich sein, um den DI-Container einzutragen, weil Sie eine Version durch verschiedene hartcodierte Regeln oder einen Test-Mock ersetzen könnten. Wie gezeigt, ist der Mangel an Zustand jedoch keine notwendige Voraussetzung, um in diesem Sinne als "Singleton" nützlich zu sein.

0

Wie es staatenlos

Sie über 'stateless' hier nicht reden machen. Siehe https://en.wikipedia.org/wiki/Stateless

Machen Sie Ihre Funktionen statisch: https://secure.php.net/manual/en/language.oop5.static.php

dh

class DirectoryUtils { 
    ... 

    public static function renameDirectory($newName) { 
     ... 
    } 

} 

dann einfach Sie es so nennen:

DirectoryUtils::renameDirectory($name); 
+0

Ich spreche nicht über statische Methode ... schau hier: http://php-di.org/doc/scopes.html – Bob

+0

Sie sprechen über Singleton dann. –

+0

Singleton-Bereich (im Zusammenhang mit PHP-DI), nicht das Singleton-Entwurfsmuster. – Bob

0

Die Grundregel für eine stateless Klasse ist nicht mit irgend Instanzvariablen/Eigenschaften zum Speichern des Status. Die Klassenmethoden ähneln der Dienstprogramm- oder Hilfsfunktion, die nur mit den Argumenten arbeitet.

Umschreiben der Klasse:

<?php 

class DirectoryUtils{  

    public function deleteAllFiles($dir){ 
    // code to delete all files in $dir; 
    } 

    public function renameDirectory($dir, $newName){ 
    // code to rename $dir name to $newName 
    } 
} 
+0

'Die Grundregel für eine zustandslose Klasse ist, keine Instanzvariablen/Eigenschaften zu haben, um den Zustand zu speichern. Warum haben Sie dann einen Konstruktor? –

+0

PHP fügt keinen Standardkonstruktor hinzu. [Referenz] (https://stackoverflow.com/questions/7909073/why-php-has-no-default-constructor). Ein Konstruktor ist jedoch nicht erforderlich, wenn alle Methoden statisch sind. – abskmj

+0

Tatsächlich kann es eine gemeinsam genutzte Eigenschaft haben, zum Beispiel eine Datenbankverbindung, die über Aufrufe hinweg geteilt werden kann. –