PHP Forum

PHP Forum (http://www.selfphp.de/forum/index.php)
-   PHP Entwicklung und Softwaredesign (http://www.selfphp.de/forum/forumdisplay.php?f=14)
-   -   OOP Zugriff auf Objekte fremden Klassen (http://www.selfphp.de/forum/showthread.php?t=23942)

elkmod 08.01.2011 17:30:57

OOP Zugriff auf Objekte fremder Klassen
 
Hallo zusammen.

Ich bin gerade dabei ein Framework zu schreiben, jedoch habe ich ein kleines Problem bei der objektorientierten Umsetzung des Ganzen.

Ich versuche mal kurz das Problem zu umreißen:
Es gibt eine Klasse BaseObject, von der alle anderen Klassen bis auf die Logs abgeleitet werden. Das BaseObject verfügt über einen Konstruktor, in dem die Log-Datei geöffnet wird, natürlich alles objektorientiert
PHP-Code:

$this->error_log = new Log("logs/error.log"); 

Das Ganze soll dazu dienen, dass später aus jedem anderen Objekt durch den Aufruf von
PHP-Code:

$this->error_log->add(Fehlermeldung); 

auf das Log-Objekt zugegriffen werden kann. Dazu ist es nützlich ein Zentrales Log-Objekt zu erzeugen, statt bei jeder Instanziierung ein neues. Beim recherchieren bin ich dabei auf die Singleton-Variante gestoßen, bei der das Objekt, soweit ich verstanden habe, nur einmal erzeugt wird und dann immer über obj->getInstance() darauf zugegriffen wird.

Die Klassen sind wie folgt aufgebaut:

Code:

BaseObject
  Config
  Controller
  Page

Log
  ErrorLog
  UserLog

Client

Wenn nun im Konstruktor von BaseObject ein Objekt der Klasse ErrorLog instanziiert wird, wie kann ich dann in Unterklassen von BaseObject auf das gleiche Objekt zugreifen ohne ein Neues erzeugen zu müssen?

Hier noch der Konstruktor von BaseObject
PHP-Code:

public function __construct()
{

  
$this->client = new Client();
  
$this->error_log LogFile::getInstance("logs/error.log");



Der Parameter bei getInstance ist da, weil das Objekt ja mindestens einmal erzeugt werden muss. Meine Frage ist jetzt, wie genau diese Funktion getInstance($path) aussehen muss, damit erst geprüft wird, ob bereits ein Objekt der Klasse existiert und dieses ggf. zurückgegeben oder erzeugt wird.

DokuLeseHemmung 08.01.2011 18:06:11

AW: OOP Zugriff auf Objekte fremden Klassen
 
Singletons sind böse!
Ein stumpfer Ersatz für globale Variablen.
Selten sinnvoll.
Was ist, wenn es mehrere (verschiedene) Logger geben soll?
Was ist, wenn du mal eine Ableitung/Kind eines Loggers verwenden willst?

Ob etwas Singleton sein darf/soll/muß, ist eine Anforderung der Applikation. Darum darf sowas in einem Framework nicht auftauchen.
Selbst die Helden des ZF haben das mittlerweile geschnallt und eliminieren jetzt alle Singletons in ihrem Framework.
Bitte tappe nicht in die gleiche Falle.




Logger über den Constructor übergeben ist auch böse!
Denn nicht immer brauchen alle Objekte einen Logger.
Das Fachwort dafür ist übrigens "Constructor Injection"
Besser wäre also die "Setter Injection".

Im Falle deiner Controller wäre es sicherlich Sinnvoll diese per "Factory" zu erzeugen.
Mache dich generell über das "Dependency Injection Pattern" kundig.
Denn witziger weise, bist du nicht die/der erste mit diesem Problem!

elkmod 16.01.2011 16:31:13

AW: OOP Zugriff auf Objekte fremden Klassen
 
Soweit ich das jetzt verstanden habe, sollen die Objekte von eienr Factory-Klasse erzeugt werden und jede Klasse, welche beispielsweise einen Logger braucht enthält dann einen "setLogger" - Dienst. Wie sieht das mit der Vererbung aus bei Klassen die einen Logger brauchen und bei welchen die keinen benötigen?

DokuLeseHemmung 16.01.2011 21:44:06

AW: OOP Zugriff auf Objekte fremden Klassen
 
Bevor ich was zur Vererbung oder Fabriken sage (was soll man dazu denn auch sagen), erstmal dieses:
1. bei notwendigen Dingen: Konstruktor injection
2. bei optionalen Dingen: Setter injection


Im folgenden Code benötigt der Logger ZWINGEND einen Dateinamen.
Also: Konstruktor injection

Aber der Rechner kann einen Logger bedienen, muss aber nicht, kommt auch ohne aus.
Also: Setter injection

So und nun endlich ein Beispiel:
PHP-Code:

<?php
error_reporting
(-1);
ini_set('display_errors'TRUE);



interface 
Logger
{
  function 
log($string);


interface 
Logable
{
  function 
setLogger(Logger $logger);


class 
FileLogger implements Logger
{
    protected 
$filename '';
  
    public function 
__construct($filename)
    {
      
$this->filename=$filename;
    }
    public function 
log($string)
    {
      
file_put_contents($this->filename,$string."\n",FILE_APPEND);
    }
}


class 
Rechner implements Logable
{
   protected 
$logger null;
   public function 
setLogger(Logger $logger)
   {
      
$this->logger $logger;
   }
   
   public function 
plus($a,$b)
   {
      
$c $a $b;
      if(
$this->logger)
      {
        
$this->logger->log("$c = $a + $b");
      }
      return 
$c;
   }
}


// testcode
$r = new Rechner;
$l = new FileLogger('./log.txt'); // Konstruktor injection

if($r instanceof Logable)
{
  
$r->setLogger($l); // Setter injection
}

echo 
$r->plus(1,2), '<br>';
echo 
$r->plus(1,3), '<br>';
echo 
$r->plus(1,4), '<br>';
echo 
$r->plus(1,5), '<br>';


elkmod 17.01.2011 01:07:31

AW: OOP Zugriff auf Objekte fremden Klassen
 
Okay, dank deiner Hilfe steige ich langsam da durch. Per Factory lass ich alle Logger usw. anfangs erzeugen und gebe sie dann gegebenenfalls den anderen Objekten per Setter Injection mit, falls diese sie benötigen.

Wenn ich mehrere Klassen habe deren Objekte, einen Logger benötigen, macht es dann Sinn eine Oberklasse, zu schreiben, welche die Methoden setLogger, setDB usw. enthält oder soll ich die Methode je nach Bedarf immer einzeln in die Klasse schreiben, was mir aber weniger sinnvoll erscheint, denn wie sieht es aus, wenn es mehrere Logger geben soll für welchen Zweck auch immer, kann man die Methoden irgendwie verallgemeinern?

DokuLeseHemmung 17.01.2011 01:24:23

AW: OOP Zugriff auf Objekte fremden Klassen
 
Zitat:

macht es dann Sinn eine Oberklasse, zu schreiben, welche die Methoden setLogger, setDB usw. enthält oder soll ich die Methode je nach Bedarf immer einzeln in die Klasse schreiben,
Das kann ich natürlich von hier aus nicht sagen.
Bedenke:
Du kannst immer nur von EINER Oberklasse erben, aber VIELE Interfaces implementieren.

Zitat:

, kann man die Methoden irgendwie verallgemeinern?
Hmm...

Sowas?
Google: "Observer Design Pattern"


Alle Zeitangaben in WEZ +2. Es ist jetzt 23:01:59 Uhr.

Powered by vBulletin® Version 3.8.3 (Deutsch)
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.