2010-11-22 9 views
0

Die Codebase, die ich zur Arbeit mit übergeben wurde, verfügt über eine Datenbankklasse, die von MDB2 erbt. Dies bildet die Grundlage für das verwendete MVC-Framework (eine benutzerdefinierte Build-Affäre) und die Modelle wiederum erben von db.Ändern einer Klasse zum Einkapseln statt Erben

Wie einige von Ihnen sicher bemerkt haben, führt dies zu einem ziemlich großen Problem. Jedes Mal, wenn Sie ein Modell instanziieren, wird eine neue Datenbankverbindung erstellt. Dies ist offensichtlich ziemlich verschwenderisch. Es bedeutet auch, dass ich Transaktionen nicht wie vorgesehen verwenden kann. Wenn eine Transaktion in einer Instanz eines Modells startet, sind ihre Auswirkungen für die anderen Instanzen unsichtbar, bis eine Festschreibung erfolgt.

Mein Plan ist es, die db-Klasse so zu ändern, dass sie MDB2 einkapselt, anstatt von ihr zu erben, und dann eine einzelne Instanz von MDB2 über ihre Singleton-Funktionalität pflegen zu lassen.

Allerdings ist MDB2 eine große Bibliothek mit vielen Methoden, und viele Dinge, die höher in der Code-Basis sind, hängen davon ab, auf MDB2-Methoden zugreifen zu können.

Gibt es eine Möglichkeit, die MDB2-Klasse einzukapseln und Aufrufe an sie zu übergeben, ohne die höheren Ebenen zu ändern und ohne eine Wrapper-Methode für jede Methode in MDB2 schreiben zu müssen?

+0

können Sie ein Beispiel Modellklasse zeigen, bitte, wir können so sehen, inwieweit sie gekoppelt sind? – Gordon

Antwort

3

Da Sie noch keinen Code angegeben haben, ist dies ein blinder Vorschlag, wie Sie die Vererbung mit sehr wenig Code entfernen können, während gleichzeitig die volle Funktionalität erhalten bleibt und sichergestellt wird, dass die MDB-Klasse nur einmal instanziiert wird.

class Db 
{ 
    protected static $_mdb; 
    public function __construct() 
    { 
     if(self::_mdb === NULL) { 
      self::_mdb = new MDB; 
     } 
    } 
    public function __call($method, $args) 
    { 
     return call_user_func_array(array(self::_mdb, $method), $args); 
    } 
} 

Dies wird Ihre DB-Klasse im Grunde zu einem Dekorator für MDB machen. Bei der ersten Instanziierung erstellt und speichert die DB-Klasse eine statische MDB-Instanz. Dies wird unter allen Instanzen von DB, einschließlich untergeordneten Klassen, geteilt. Es gibt keinen Grund, einen Singleton hier zu verwenden.

Der Interceptor __call stellt sicher, dass alle Methoden, die Sie in DB aufgerufen haben, die Methoden der MDB-Methode aufrufen, abgefangen und an die MDB-Instanz delegiert werden. Magische Methoden können schwerwiegende Auswirkungen auf die Leistung haben. Wenn Sie Leistungseinbußen feststellen, fügen Sie der DB-Klasse alle aufgerufenen Methoden hinzu und delegieren Sie von dort aus.

Unnötig zu sagen, dies noch nicht die beste Lösung ist, weil Ihre DB-Instanz fest noch zu Ihren Modellklassen gekoppelt ist. Wenn Sie mehr Refactoring leisten können, würde ich vorschlagen, alle Klassen zu machen, die derzeit von der DB erben kapseln die DB-Instanz statt (es sei denn, sie sind ActiveRecords). Verwenden Sie dann Dependency Injection, um die DB-Instanz verfügbar zu machen.