Design Patterns in Magento 2: Der vollständige Überblick (13+ Patterns)
{ }
DI
Magento 2 Architektur & PHP Patterns

Design Patterns in
Magento 2

DI, Repository, ViewModel, Plugin, Observer, Factory, Proxy, MVC, Strategy, Iterator, Active Record, Singleton, Registry und mehr – alle 13+ Architekturmuster in Magento 2 erklärt, mit Code-Beispielen und dem Wissen, wann welches Pattern der richtige Griff ist.

⏱ 25 Min. Lesezeit 13+ Design Patterns PHP 8.4 Vollständige Referenz

Warum Design Patterns in Magento 2 unverzichtbar sind

Magento 2 ist nicht einfach ein E-Commerce-Framework – es ist ein durchdachtes Softwaresystem, das konsequent auf bewährten Design Patterns aufbaut. Wer Magento-Module entwickelt, ohne diese Muster zu kennen, kämpft ständig gegen den Strom: Code wird brüchig, Upgrades brechen Anpassungen, und Unit-Tests sind kaum möglich.

Design Patterns sind wiederverwendbare Lösungsvorlagen für häufig wiederkehrende Softwareprobleme. Sie wurden von der sogenannten „Gang of Four" (Gamma, Helm, Johnson, Vlissides) in ihrem 1994 erschienenen Klassiker systematisiert. Magento 2 greift diese Konzepte auf und erweitert sie um eigene Muster, die speziell auf die Anforderungen eines Enterprise-E-Commerce-Systems zugeschnitten sind.

Dieser Artikel gibt einen vollständigen Überblick über alle relevanten Design Patterns in Magento 2 – von den fundamentalen wie Dependency Injection bis hin zu Magento-spezifischen Mustern wie dem Plugin/Interceptor Pattern. Jedes Pattern wird mit seiner Motivation, seiner Implementierung und einem konkreten Code-Beispiel erklärt. Die Vertiefung in die einzelnen Patterns erfolgt in den verlinkten Spezialbeiträgen.

1. Was sind Design Patterns?

Design Patterns sind keine fertigen Code-Bibliotheken, die man einfach importiert. Sie sind konzeptuelle Vorlagen – abstrakte Beschreibungen von Klassenstrukturen und Interaktionen, die ein bestimmtes, häufig auftretendes Designproblem lösen. Man unterscheidet drei Kategorien:

  • Creational Patterns (Erzeugungsmuster): Steuern, wie Objekte erstellt werden. Beispiel: Factory, Builder, Singleton.
  • Structural Patterns (Strukturmuster): Definieren, wie Klassen und Objekte zusammengesetzt werden. Beispiel: Proxy, Composite, Decorator.
  • Behavioral Patterns (Verhaltensmuster): Regeln die Kommunikation zwischen Objekten. Beispiel: Observer, Command, Strategy.

Magento 2 nutzt alle drei Kategorien – und fügt mit dem Plugin/Interceptor Pattern ein eigenes, Magento-spezifisches Muster hinzu, das es in dieser Form in keinem anderen Framework gibt.

2. Dependency Injection (DI)

Das Dependency Injection Pattern ist das Fundament der gesamten Magento 2 Architektur. Ohne ein Verständnis von DI ist kein sinnvolles Magento-Entwickeln möglich.

Das Problem ohne DI

Ohne DI instanziieren Klassen ihre Abhängigkeiten selbst – mit new. Das macht Code schwer testbar (weil Abhängigkeiten nicht austauschbar sind) und schwer erweiterbar (weil Abhängigkeiten hart kodiert sind).

Dependency Injection in Magento 2

In Magento 2 werden alle Abhängigkeiten über den Konstruktor injiziert. Der Magento ObjectManager (Dependency Injection Container) liest die Typ-Hinweise in den Konstruktor-Parametern und instanziiert die benötigten Objekte automatisch. Seit PHP 8.0 nutzt Magento dafür Constructor Property Promotion.

Die Konfiguration, welche Klasse für ein Interface verwendet wird, erfolgt in der di.xml:

Vorteile: Testbar (Mock-Implementierungen injizierbar), austauschbar (andere Implementierung via di.xml), erweiterbar (ohne Core-Änderungen). DI ist das Rückgrat von Magento – fast jedes andere Pattern baut darauf auf.

→ Vertiefung: Dependency Injection in Magento 2

3. Repository Pattern & Service Contracts

Das Repository Pattern kapselt den Datenzugriff hinter einem stabilen Interface. In Magento 2 werden Repositories als Teil der Service Contracts definiert – einem der wichtigsten Architekturprinzipien von Magento 2.0+.

Service Contracts: Das Versprechen stabiler APIs

Service Contracts sind PHP-Interfaces unter dem Namespace Api/ eines Moduls. Sie definieren die öffentliche API eines Moduls und garantieren Abwärtskompatibilität über Upgrades hinweg. Niemand soll eine konkrete Magento-Klasse direkt instanziieren – stattdessen injiziert man das Interface.

Die konkrete Implementierung in Model/ProductRepository.php enthält die eigentliche Datenbanklogik. Klassen, die Produkte benötigen, injizieren ausschließlich das Interface – nie die Implementierung direkt.

Vorteile: Klarer Datenzugriffslayer, testbar mit Mocks, stabile API über Upgrades, REST/GraphQL-Exposition möglich.

→ Vertiefung: Repository Pattern & Service Contracts

4. ViewModel Pattern

Das ViewModel Pattern ist die moderne Antwort auf das Problem der aufgeblähten Magento Block-Klassen. Statt die gesamte Präsentationslogik in Block-Klassen zu stopfen, die tief in der Magento-Klassenhierarchie verwurzelt sind, verwendet man leichtgewichtige ViewModels.

Das Problem mit Block-Klassen

Block-Klassen in Magento erben von Magento\Framework\View\Element\Template, die ihrerseits von Magento\Framework\View\Element\AbstractBlock erbt – einer sehr komplexen Basisklasse mit Caching, Layout-Referenzen und Render-Logik. Eigene Logik in Blöcken ist schwer testbar und eng an das Magento-Framework gebunden.

Das ViewModel wird per Layout-XML als Argument an den Block übergeben und im Template verwendet:

Vorteile: Einfach unit-testbar, keine Magento-Basisklassen-Abhängigkeit, klare Trennung von View-Logik und Rendering, leicht austauschbar via di.xml.

→ Vertiefung: ViewModel Pattern in Magento 2

5. Plugin / Interceptor Pattern

Das Plugin Pattern ist Magentos Antwort auf ein klassisches Problem: Wie kann man das Verhalten einer bestehenden Klasse verändern, ohne diese Klasse direkt zu bearbeiten? Das ist besonders im Kontext von Drittanbieter-Modulen und Core-Erweiterungen entscheidend.

Die drei Plugin-Typen

Magento kennt drei Arten von Plugins, die alle über die di.xml registriert werden:

  • Before Plugin: Wird vor der ursprünglichen Methode ausgeführt. Kann die Eingabeparameter modifizieren.
  • After Plugin: Wird nach der ursprünglichen Methode ausgeführt. Kann den Rückgabewert modifizieren.
  • Around Plugin: Umschließt die ursprüngliche Methode komplett. Entscheidet, ob und wie die Originalmethode aufgerufen wird.

Vorteile: Kein Core-Override nötig, mehrere Plugins können koexistieren, upgrade-sicher, sauber deaktivierbar.

Wichtig: Around-Plugins sollten sparsam eingesetzt werden, da sie die gesamte Plugin-Chain beeinflussen. Before- und After-Plugins sind in der Regel ausreichend.

→ Vertiefung: Plugin / Interceptor Pattern in Magento 2

6. Observer / Event Pattern

Das Observer Pattern (auch bekannt als Publisher-Subscriber Pattern) ermöglicht lockere Kopplung zwischen Modulen. Ein Modul dispatcht ein Event, ohne zu wissen, wer darauf reagiert. Andere Module können Observer registrieren, die auf dieses Event reagieren.

Vorteile: Vollständige Entkopplung zwischen Modulen, mehrere Observer pro Event, leicht deaktivierbar, kein Wissen über Empfänger nötig.

Plugin vs. Observer: Plugins modifizieren Methoden-Verhalten. Observer reagieren auf Ereignisse. Beide dienen der Erweiterung ohne Core-Änderungen, aber für unterschiedliche Szenarien.

→ Vertiefung: Observer / Event Pattern in Magento 2

7. Factory Pattern

Das Factory Pattern delegiert die Objekterzeugung an eine dedizierte Fabrikklasse. In Magento 2 werden Factories automatisch vom Code-Generator erstellt – man muss sie in der Regel nicht selbst schreiben.

Warum keine direkte Instanziierung mit new? Weil dann die gesamte DI-Konfiguration (Preferences, Plugins, Shared-Flag) umgangen wird. Factories respektieren die komplette ObjectManager-Konfiguration.

8. Proxy Pattern

Proxies in Magento 2 sind Lazy-Loading-Wrapper. Sie werden eingesetzt, wenn eine Klasse eine teure Abhängigkeit hat, die nur in bestimmten Fällen benötigt wird. Statt die Abhängigkeit sofort zu instanziieren, injiziert man einen Proxy, der das echte Objekt erst bei Bedarf erstellt.

Anwendungsfälle: Schwere Services, die auf allen Seiten injiziert werden müssen, aber nur auf spezifischen Seiten genutzt werden. Typisch: Customer Session, Catalog Rule Indexer, Full Page Cache Flusher.

9. Builder Pattern

Das Builder Pattern konstruiert komplexe Objekte Schritt für Schritt. In Magento 2 wird es am häufigsten für SearchCriteria-Objekte verwendet – die Suchanfragen für Repositories.

10. Composite Pattern

Das Composite Pattern behandelt einzelne Objekte und Zusammensetzungen von Objekten einheitlich. In Magento 2 ist das Layout-System ein klassisches Beispiel: Sowohl einzelne Blöcke als auch Container von Blöcken können gerendert werden, weil beide dieselbe render()-Schnittstelle implementieren.

Weitere Composite-Strukturen in Magento: Config-Merge-Bäume, UI Components, Pricing-Modelle, Sales-Rule-Conditions.

11. MVC & Front Controller Pattern

Magento 2 basiert auf dem MVC Pattern — aber nicht in seiner klassischen Form. Der Controller kennt den View nicht direkt. Stattdessen gibt er ein ResultInterface-Objekt zurück, das definiert welche Layout-Konfiguration gerendert wird. Die Datenbereitstellung übernehmen Block-Klassen oder ViewModels.

Das Front Controller Pattern sorgt dafür, dass alle HTTP-Requests über einen einzigen Einstiegspunkt laufen: pub/index.php. Von dort übernimmt Magento\Framework\App\FrontController die Weiterleitung durch mehrere Router (Base, CMS, URL-Rewrite, Default) in definierter sortOrder.

Der Layout-Handle ergibt sich aus: {routeId}_{controllerFolder}_{actionName}.

→ Vertiefung: MVC & Front Controller Pattern

12. Strategy Pattern

Das Strategy Pattern definiert eine Familie von Algorithmen, kapselt jeden einzeln und macht sie austauschbar. Der Kontext kennt nur das Interface — nicht die konkrete Implementierung.

In Magento 2 steckt das Strategy Pattern in jedem Versandträger (AbstractCarrier), jeder Payment-Methode und jeder Preisberechnung. Jeder Carrier implementiert collectRates() nach seiner eigenen Logik.

Für eigene Strategien: Interface definieren, Implementierungen erstellen, in di.xml als Pool injizieren. Neue Strategie hinzufügen = neue Klasse + di.xml-Eintrag, kein bestehender Code wird geändert (Open/Closed Principle).

→ Vertiefung: Strategy Pattern in Magento 2

13. Iterator Pattern & Collections

Das Iterator Pattern stellt eine einheitliche Schnittstelle bereit, um über eine Sammlung von Objekten zu iterieren — ohne die interne Struktur zu kennen. In Magento 2 implementiert AbstractCollection das IteratorAggregate-Interface, was direkte foreach-Iteration ermöglicht.

Collections sind lazy: Die SQL-Abfrage wird erst beim ersten Datenzugriff ausgeführt. Für Flat Tables: addFieldToFilter(). Für EAV-Attribute: addAttributeToFilter().

→ Vertiefung: Iterator Pattern & Collections

14. Active Record Pattern

Das Active Record Pattern kombiniert Domain-Objekt und Datenbankzugriff in einer Klasse. In Magento 2 ist das AbstractModel: jede Model-Klasse hat load(), save() und delete() direkt am Objekt.

Wichtig: load() ist seit Magento 2.4.x als @deprecated markiert. Für neue Module das Repository Pattern verwenden. Magic Getter/Setter (getName(), setTitle()) kommen von DataObject und sind nicht typsicher — Data Interfaces sind die bessere Alternative.

→ Vertiefung: Active Record Pattern in Magento 2

15. Preferences

Preferences sind der stärkste Eingriff in den Magento DI-Container: Eine gesamte Klasse wird systemweit durch eine andere ersetzt. In di.xml mit <preference for="..." type="..."/> definiert.

Der häufigste und legitimste Anwendungsfall: Interface-Preferences, die eine konkrete Implementierung für ein Interface registrieren. Für konkrete Klassen gilt: Preference nur wenn neue Methoden benötigt werden, die ein Plugin nicht hinzufügen kann. Ansonsten Plugin bevorzugen — Plugins koexistieren, Preferences kollidieren.

→ Vertiefung: Preferences in Magento 2

16. Singleton & Registry Pattern (Anti-Patterns)

Das Singleton Pattern stellt sicher, dass von einer Klasse nur eine Instanz existiert. In Magento 2 wird das über Shared Instances im DI-Container umgesetzt — akzeptabel für stateless Services. Problematisch wird es bei mutierbarem globalem Zustand: Tests beeinflussen sich gegenseitig, Async-Prozesse teilen State.

Das Registry Pattern (Magento\Framework\Registry) ist ein globaler Schlüssel-Wert-Speicher — aus Magento 1 übernommen und seit 2.4.x als @deprecated markiert. Nicht mehr in neuen Modulen verwenden. Alternative: Constructor Injection, ViewModel, Event-Daten.

→ Vertiefung: Singleton & Registry (Anti-Patterns)

17. Service Locator & ObjectManager (Anti-Pattern)

Das Service Locator Pattern fordert Abhängigkeiten aktiv von einer zentralen Registry an — statt sie per Konstruktor zu empfangen. In Magento 2 ist das der ObjectManager.

Direkter ObjectManager-Aufruf in Business-Logik ist verboten: Er umgeht Plugins, Preferences und statische Analyse. Ausnahmen: Bootstrap-Code, generierte Factories, Integration-Tests. PHPCS mit Magento2-Standard erkennt Verstöße automatisch.

→ Vertiefung: Service Locator & ObjectManager Anti-Pattern

18. Injectable/Non-Injectable & Virtual Types

Injectable Objects sind stateless Services ohne $data-Parameter im Konstruktor — Repositories, Logger, Factories. Sie werden als Shared Instance verwaltet und direkt injiziert.

Non-Injectable Objects haben veränderlichen Zustand (Models, DTOs, Collections). Sie dürfen nicht direkt injiziert werden — stattdessen eine Factory verwenden (PostFactory erzeugt je eine neue Post-Instanz).

Virtual Types ermöglichen neue Klassenkonfigurationen ohne PHP-Code: In di.xml eine Klasse mit anderen Konstruktor-Argumenten registrieren. Typisches Beispiel: Modul-spezifischer Logger.

→ Vertiefung: Injectable/Non-Injectable & Virtual Types

19. Prototype & Object Pool Pattern

Das Prototype Pattern erzeugt neue Objekte durch Klonen eines bestehenden Prototyps. In Magento 2 bei Produkttypen (jeder Typ ist ein Prototyp) und Quote Items (Kinder-Items als clone des Parent-Items).

Das Object Pool Pattern hält einen Vorrat vorinstanziierter, wiederverwendbarer Objekte bereit. Magento nutzt es implizit über Shared Instances im DI-Container und explizit über ResourceConnection für Datenbankverbindungen.

→ Vertiefung: Prototype & Object Pool Pattern

20. Wann welches Pattern?

Die Entscheidung, welches Pattern für welches Problem das richtige ist, ist eine der wichtigsten Fähigkeiten eines Magento-Architekten. Hier ist eine Entscheidungshilfe:

Wann welches Design Pattern in Magento 2? Pattern Einsatz wenn … Nicht geeignet wenn … Dependency Injection Klassen Abhängigkeiten brauchen — (immer verwenden!) Repository Pattern CRUD-Operationen für Entities Komplexe Multi-Entity-Queries (→ Resource Models) ViewModel Pattern Logik für phtml-Templates kapseln Schwere Render-Logik (→ Block bleibt) Plugin / Interceptor Verhalten einer Methode ändern/erweitern Auf finale Klassen, private Methoden Observer / Event Entkoppelte Reaktion auf Ereignisse Wenn Rückgabewert modifiziert werden soll Factory Pattern Neue Objekte erzeugen (nicht Singletons) Wenn Singleton ausreicht (→ direkte Injektion) Proxy Pattern Teure Klasse nur manchmal gebraucht Klasse wird immer benötigt (kein Nutzen) Builder Pattern Komplexe Objekte schrittweise aufbauen Einfache Objekte (→ direkte Konstruktion) Composite Pattern Bäume/Hierarchien einheitlich behandeln Flache Strukturen ohne Hierarchie

Mironsoft

Magento 2 Architektur & Entwicklung

Magento 2 Architektur professionell umsetzen?

Wir entwickeln saubere, upgrade-sichere Magento 2 Module mit den richtigen Design Patterns. Code-Reviews, Architekturberatung und Modul-Entwicklung nach Best Practices.

Modul-Entwicklung

Saubere Module mit DI, Service Contracts, ViewModels und Tests

Code-Review

Bestehenden Code analysieren, Patterns korrekt anwenden

Upgrade-Sicherheit

Code ohne Core-Overrides, Plugins statt Preferences

21. Zusammenfassung

Design Patterns in Magento 2 sind keine akademischen Konzepte – sie sind die tägliche Werkzeugkiste jedes professionellen Magento-Entwicklers. Das Fundament bildet Dependency Injection, auf dem alle anderen Patterns aufbauen. Service Contracts und Repositories definieren stabile APIs. ViewModels halten Templates sauber. Plugins erweitern Verhalten ohne Core-Eingriff. Observer entkoppeln Module vollständig.

Design Patterns in Magento 2 – Das Wichtigste auf einen Blick

Basis: Dependency Injection

Alles über den Konstruktor injizieren. Interfaces statt Implementierungen injizieren. Constructor Property Promotion nutzen. Factories für neue Objekte.

Erweiterung: Plugin vor Observer

Plugins wenn Methoden-Verhalten geändert werden soll. Observer wenn auf Ereignisse reagiert werden soll – ohne Rückgabewert. Around-Plugins sparsam nutzen.

Datenzugriff: Repository Pattern

Service Contracts für öffentliche APIs. Repositories für CRUD. SearchCriteriaBuilder mit FilterBuilder für Suchanfragen. Interfaces injizieren, nie Implementierungen.

Templates: ViewModel Pattern

Logik aus Templates in ViewModels auslagern. ArgumentInterface implementieren. Via Layout-XML als Argument übergeben. Leicht unit-testbar, kein Magento-Framework nötig.

22. FAQ: Design Patterns in Magento 2

1 Plugin vs. Observer – was ist der Unterschied?
Plugins hängen an spezifische Methoden und können Input/Output modifizieren. Observer reagieren auf Events, können aber keine Rückgabewerte ändern. Plugins für Methoden-Modifikation, Observer für entkoppelte Event-Reaktionen zwischen Modulen.
2 Wann Preference statt Plugin?
Fast nie. Preferences überschreiben eine Klasse komplett und führen zu Upgrade-Konflikten. Plugins sind in 95% der Fälle die richtige Wahl. Preferences nur wenn die Zielklasse final ist und Plugins nicht greifen können.
3 Warum immer Interface injizieren statt Klasse?
Interface-Injektion entkoppelt Code von der Implementierung. Via di.xml kann eine andere Implementierung konfiguriert werden – ohne die injizierende Klasse zu ändern. Macht Code testbar (Mocks) und austauschbar.
4 Factory vs. Proxy – was ist der Unterschied?
Factory: erstellt bei jedem Aufruf eine neue Instanz (non-shared). Proxy: Lazy-Loading-Wrapper, der die Instanziierung verzögert bis zum ersten echten Zugriff. Factory für neue Objekte, Proxy für Performanz-Optimierung bei teuren Singletons.
5 Wann ViewModel statt Block?
Immer wenn Logik für ein Template gekapselt werden soll. ArgumentInterface implementieren, keine Magento-Basisklasse nötig. Leicht unit-testbar. Block nur noch wenn Magento-spezifische Render-Funktionen nötig sind (getCacheKeyInfo, etc.).
6 Was ist Constructor Property Promotion in Magento 2?
PHP 8.0+ Feature: Kombination von Parameter-Deklaration und Property-Zuweisung im Konstruktor. Statt private $repo; public function __construct(RepoInterface $repo) { $this->repo = $repo; } schreibt man nur: public function __construct(private readonly RepoInterface $repo) {}. Weniger Boilerplate, klarer Code.