Koledze nie o to chodzi, czy i gdzie wykorzystać singleton. Jeśli nawet wykorzysta ten wzorzec, to nadal jego problem nie będzie rozwiązany.
@zielu001: Z Twojego opisu wynika, że klasa EngineInit jest niejako klasą główną, a metoda EngineStart ma zainicjować konfigurację, bazę danych i sesje, z których później będziesz korzystał. Jednak w kodzie, który nam pokazałeś tworzysz tylko zmienne lokalne, działające w obrębie metody EngineStart. Nie będziesz miał zatem możliwości posługiwania się nimi później. Dlatego klasa mogłaby/powinna wyglądać nieco inaczej:
class EngineInit {
private $_configuration = null;
private $_database = null;
private $_session = null;
public function EngineStart() {
$this->_configuration = new ConfigurationInit;
$this->_database = new DataBaseLoader;
$this->_session = new SessionsLoader;
}
}
Teraz przejdźmy do meritum. Jeśli obiekt klasy DatabaseLoader (
i tutaj nieważne, czy jest to singleton, czy nie), czy też klasy SessionLoader musi skorzystać z danych zawartych w obiekcie klasy ConfigurationInit, to trzeba te informacje przekazać. Jak to zrobić? Otóż można posłużyć się "mechanizmem" DI (dependency injection, wstrzykiwanie zależności). Metoda EngineStart wyglądałaby zatem trochę inaczej:
class EngineInit {
// ...
public function EngineStart() {
$this->_configuration = new ConfigurationInit;
$this->_database = new DataBaseLoader($this->_configuration);
$this->_database = DataBaseLoader::getInstance($this->_configuration); // jeśli klasa DataBaseLoader będzie singletonem
$this->_session = new SessionLoader($this->_configuration);
}
}
Teraz konstruktory klas DataBaseLoader i SessionLoader mogą skorzystać z informacji, jakie "posiada" obiekt klasy ConfigurationInit. Gwoli dopełnienia formalności uzupełnijmy dla przykładu klasę DataBaseLoader:
// tutaj zwykła (nie będąca Singletonem) klasa DataBaseLoader
class DataBaseLoader {
// ...
public function __construct($configuration) {
$this->_connection = $this->connect($configuration->getDbHost(), $configuration->getDbUser(), $configuration->getDbPassword()); // przykład
}
}
Innym "mechanizmem" jest Dependency Non-Injection (uzależnianie bez wstrzykiwania). Mechanizm ten polega na zainicjowaniu "na sztywno" obiektu klasy, z której potrzebujemy skorzystać. Tak mogłaby wyglądać klasa DataBaseLoader wykorzystująca Dependency Non-Injection
class DataBaseLoader {
// ...
private $_configuration = null
public function __construct() {
$this->_configuration = new ConfigurationInit;
$this->_connection = $this->connect($this->_configuration->getDbHost(), $this->_configuration->getDbUser(), $this->_configuration->getDbPassword()); // przykład
}
}
O tym, który z przedstawionych mechanizmów wybrać musisz zdecydować sam. Dependency Injection daje nam sporą elastyczność, ponieważ przekazywane obiekty nie muszą być obiektami dokładnie jednej klasy, choć muszą spełniać założenia pewnych wzorców, które nazywamy interfejsami. Dependency Non-Injection samo w sobie nie zapewnia nam żadnej elastyczności i wymusza na nas korzystnie z dokładnie takiej, a nie innej klasy (czasami jednak właśnie tego potrzebujemy).
Wszystkie napisane wyżej klasy, to tylko przykłady. W rzeczywistości konstruktor klasy obsługującej połączenie z bazą danych nie potrzebuje wszystkich danych konfiguracyjnych, a tylko niektórych (tzn. nazwa/adres serwera, nazwa i hasło użytkownika bazy danych, czy kodowanie połączenia). Wystarczyłoby zatem przekazać konstruktorowi klasy DataBaseLoader tablicę zawierającą wymagane dane, a nie cały obiekt klasy ConfigurtionInit.
EDIT1: Poprawiłem parę literówek, ale chyba jeszcze jakieś są.
EDIT2: Problem i jego rozwiązanie z dziedziczeniem nie mają nic wspólnego.