Einfache Implementation einer Dependency Injection und das Henne/Ei-Problem

NTDY

Erfahrenes Mitglied
Ich möchte eine einfache Form der Dependency Injection nach der folgenden Idee realiseren.

Ich habe unterschiedliche Klassen Car, Ship, Bobby und Plane.

Ich habe ein Array in dem die Abhängigkeiten von Klassen zueinander gespeichert sind.

Nun sollen diese Klassen der entsprechenden Reihenfolge her aufgerufen werden und Klassen, die benötigt werden, sollen über ein Array in die aktuelle Klasse injiziert werden.

Nun habe ich das Gefühl, dass ich ein Henne / Ei Problem geschaffen habe, da ich nicht darauf komme, wie ich eine Klasse instanziieren kann und diese dann als Klasse für eine andere Klasse weitergebe.

Ich habe bereits den folgenden Code vorbereitet und vielleicht hat jemand eine Idee.

P.S. Die Klassen Plane, Ship, Car und Bobby sind identisch aufgebaut.

index.php
Code:
<pre>
<?php
require_once('Car.php');
require_once('Ship.php');
require_once('Plane.php');
require_once('Bobby.php');

// Abhängigkeiten
// Bobby:  keine Abhängigkeit
// Ship:  keine Abhängigkeit
// Plane:  hängt ab von Bobby
// Car:  hängt ab von Plane und Ship
// Klassen-Aufrufabfolge: Bobby -> Ship -> Plane -> Car

function dependencies($d){
  $array = array();
  foreach($d as $key=>$val){
  $array[$val] = '';
  }
  return $array;
}

function classcall($class,$dep){
  $instance = new $class($dep);
  return $instance->call();
}

$classes = array('Bobby'=>array(),'Ship'=>array(),'Plane'=>array('Bobby'),'Car'=>array('Plane','Ship'));
$c = '';
foreach($classes as $class=>$dependencies){
  $dep = dependencies($dependencies);
  $c .= classcall($class,$dep);
}

print_r($c);
?>

Car.php
Code:
<?php
class Car{
  protected $name = '';
  function __construct($array=array()){
   echo "<hr>";
   echo "CAR<br>";
   print_r($array);
  }

  public function call(){
   return "CAR";
  }

  public function setName($name){
   $this->name = $name;
  }

  public function getName(){
   return $this->name;
  }
}
?>

Ship.php
Code:
<?php
class Ship{
  protected $name = '';
  function __construct($array=array()){
   echo "<hr>";
   echo "SHIP<br>";
   print_r($array);
  }

  public function call(){
   return "SHIP";
  }

  public function setName($name){
   $this->name = $name;
  }

  public function getName(){
   return $this->name;
  }
}
?>

Plane.php
Code:
<?php
class Plane{
  protected $name = '';
  function __construct($array=array()){
   echo "<hr>";
   echo "PLANE<br>";
   print_r($array);
  }

  public function call(){
   return "PLANE";
  }

  public function setName($name){
   $this->name = $name;
  }

  public function getName(){
   return $this->name;
  }
}
?>

Bobby.php
Code:
<?php
class Bobby{
  protected $name = '';
  function __construct($array=array()){
   echo "<hr>";
   echo "BOBBY<br>";
   print_r($array);
  }

  public function call(){
   return "BOBBY";
  }

  public function setName($name){
   $this->name = $name;
  }

  public function getName(){
   return $this->name;
  }
}
?>
 
Ich glaube, dass Du das Prinzip der Dependency Injection falsch verstehst. Insofern wäre es wohl sinnvoll, wenn Du uns erklären würdest, was Du vor hast, und dann können wir Dir auch konkret helfen und zeigen, wie man bei Deinem Problem dieses Entwurfsmuster korrekt umsetzt.
 
Mein Ziel ist, dass ich für jede Klasse definiere, von welcher sie abhängig ist. In der entsprechenden Reihenfolge werden dann Klassen sortiert aufgerufen.
Klasse "Bobby" und "Ship" hängt von nichts ab, macht seine Operationen.
Dann wird Klasse "Plane" aufgerufen. Die Klasse "Bobby" wird von "Plane" benötigt, also wird sie in die Klasse "Bobby" über den Ship-Konstruktor injiziert.
Nun macht Ship seine Operationen und Operationen auf die Klasse Bobby.
usw.
Die Klassen, die über den Konstruktur eingebunden werden sollen, können beliebig sein. Daher meine Idee auch mit dem Array, die Objekte beinhalten.
 
Was heißt denn bei Dir, dass die Klassen "beliebig" sein können? Können es unterschiedlich viele Klassen/Objekte sein oder heißt es, dass es egal ist, welche Klasse jetzt genau eingebunden wird? Bei ersterem sehe ich das Problem, dass Du dann nicht genau definiert hast, auf welche Klasse Du jetzt genau zugreifen willst. Letzteres kannst Du über Interfaces lösen.

PHP:
class Bobby {

}

class Plane {
  private $bobby;

  public function __construct( Bobby $bobby ) {
    $this->bobby = $bobby;
  }

  public function setBobbyName( $name ) {
    $this->bobby->setName( $name );
  }
}
 
Ich habe jetzt das geschrieben was ich mir vorgestellt habe. Keine Ahnung ob das DI ist, aber meine Vorstellung ist, dass ich in einer Abhängigkeitsliste definieren kann, in welches Objekt andere Objekte reinkönnen.

PHP:
<?php
class Frau{
  protected $name = '';
  function __construct($array=array()){
  }

  public function call(){
  $this->setName('Maria');
  }

  public function setName($name){
  $this->name = $name;
  }

  public function getName(){
  return $this->name;
  }
}
?>

PHP:
<?php
class Mann{
  protected $name = '';
  function __construct($array=array()){

  }

  public function call(){
  $this->setName('Josef von Nazaret');
  }

  public function setName($name){
  $this->name = $name;
  }

  public function getName(){
  return $this->name;
  }
}
?>

PHP:
<?php
class Kind{
  protected $name = '';
  protected $obj_array = array();

  function __construct($obj_array=array()){
  $this->obj_array = $obj_array;
  }

  public function call(){
  $this->setName('Jesus von Nazaret');
  $this->obj_array['Frau']->setName('Maria (Nachname unbekannt)');
  }

  public function setName($name){
  $this->name = $name;
  }

  public function getName(){
  return $this->name;
  }

  function __destruct() {
  unset($this->obj_array);
  }
}
?>

PHP:
<?php
class Kindeskinder{
  protected $name = '';
  function __construct($obj_array=array()){
  $this->obj_array = $obj_array;
  }

  public function call(){
  $this->obj_array['Mann']->setName('Josef von Nazaret (Vater von Jesus)');
  }

  public function setName($name){
  $this->name = $name;
  }

  public function getName(){
  return $this->name;
  }
}
?>

PHP:
<pre>
<?php
require_once('Kindeskinder.php');
require_once('Mann.php');
require_once('Kind.php');
require_once('Frau.php');

// Abhängigkeiten
// Bobby:  keine Abhängigkeit
// Ship:  keine Abhängigkeit
// Plane:  hängt ab von Bobby
// Car:  hängt ab von Plane und Ship
// Klassen-Aufrufabfolge: Bobby -> Ship -> Plane -> Car

$classes = array('Frau'=>array(),'Mann'=>array(),'Kind'=>array('Frau'),'Kindeskinder'=>array('Kind','Mann'));
$obj_array = array();

foreach($classes as $class=>$dependencies){
  $d = array();
  if(!empty($dependencies)){
  foreach($dependencies as $key=>$val){
  $d[$val] = $obj_array[$val];
  }
  }
  $instance = new $class($d);
  $ee = $instance->call();
  $obj_array[$class] = $instance;
  unset($d);
}

print_r($obj_array);

?>

Und das Resultat ist dann:
Code:
Array
(
[Frau] => Frau Object
(
[name:protected] => Maria (Nachname unbekannt)
)

[Mann] => Mann Object
(
[name:protected] => Josef von Nazaret (Vater von Jesus)
)

[Kind] => Kind Object
(
[name:protected] => Jesus von Nazaret
[obj_array:protected] => Array
(
[Frau] => Frau Object
(
[name:protected] => Maria (Nachname unbekannt)
)

)

)

[Kindeskinder] => Kindeskinder Object
(
[name:protected] =>
[obj_array] => Array
(
[Kind] => Kind Object
(
[name:protected] => Jesus von Nazaret
[obj_array:protected] => Array
(
[Frau] => Frau Object
(
[name:protected] => Maria (Nachname unbekannt)
)

)

)

[Mann] => Mann Object
(
[name:protected] => Josef von Nazaret (Vater von Jesus)
)

)

)

)
 
Das Problem, was ich bei Deinem Beispiel habe, ist ein Verständnisproblem, denn letztendlich willst Du einerseits dynamisch arbeiten (Array mit Abhängigkeiten), greifst aber andererseits direkt auf feste Indizes zu. Außerdem erzeugst Du somit eine direkte Abhängigkeit, weil Du innerhalb der Klassen, die von anderen abhängig sind, die Objekte instanziieren oder laden musst. Ich verstehe schon, was Du hier mit Dependency Injection willst, aber Du gehst es aus meiner Sicht falsch an.

PHP:
class Person {
  private $name;

  public function getName() {
    return $this->name;
  }

  public function setName( $name ) {
    $this->name = $name;
  }
}

class Woman extends Person {}
class Man extends Person {}

class Child extends Person {
  private $mother;
  private $father;
  
  public function __construct() {
    $this->setName( 'Jesus von Nazareth' );
  }
  
  public function defineMother( Woman $person ) {
    $this->mother = $person;
    $this->mother->setName( 'Maria (Nachname unbekannt)' );
  }

  public function defineFather( Man $person ) {
    $this->father = $person;
    $this->father->setName( 'Joseph (Nachname unbekannt)' );
  }
}
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück