Most commonly used design patterns
1. MODEL VIEW CONTROLLER (MVC) PATTERN:
The MVC pattern is a software architectural design that separates an application into three interconnected components: Model (data and business logic), View (presentation and user interface), and Controller (handles user input and interaction). In Magento 2, this pattern ensures a clear separation of concerns and facilitates modular development and maintenance.
Model:
// app/code/Vendor/Module/Model/Item.php
class Vendor_Module_Model_Item extends \Magento\Framework\Model\AbstractModel {
// Model logic
}View:
<!-- app/code/Vendor/Module/view/frontend/layout/module_index_index.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="content">
<block class="Vendor\Module\Block\Item" template="Vendor_Module::item.phtml" />
</referenceBlock>
</body>
</page>Controller:
// app/code/Vendor/Module/Controller/Index/Index.php
class Index extends \Magento\Framework\App\Action\Action {
public function execute() {
$this->_view->loadLayout();
$this->_view->renderLayout();
}
}
2. FRONT CONTROLLER PATTERN:
The Front Controller pattern centralizes request handling in an application. In Magento 2, the index.php file acts as the front controller, receiving all HTTP requests and dispatching them to the appropriate controllers. This pattern allows for a single point of entry and simplifies the handling of requests.
Example:
// pub/index.php
use Magento\Framework\App\Bootstrap;
require __DIR__ . '/../app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$objectManager = $bootstrap->getObjectManager();
/** @var \Magento\Framework\App\Http $app */
$app = $objectManager->create(\Magento\Framework\App\Http::class);
$app->launch();
3. FACTORY PATTERN:
The Factory Pattern is a creational pattern that provides an interface for creating instances of classes without specifying their concrete classes. In Magento 2, factories are commonly used to instantiate objects, especially models. Factories abstract the process of object creation, making the system more flexible and maintainable.
Example:
// app/code/Vendor/Module/Controller/Index/Index.php
class Index extends \Magento\Framework\App\Action\Action {
protected $itemFactory;
public function __construct(\Vendor\Module\Model\ItemFactory $itemFactory) {
$this->itemFactory = $itemFactory;
}
public function execute() {
$item = $this->itemFactory->create();
// Perform actions with $item
}
}4. SINGLETON PATTERN:
The Singleton Pattern ensures that a class has only one instance and provides a global point of access to that instance. In Magento 2, singleton instances are often used for shared resources and services, ensuring that only one instance is created and reused throughout the application.
Example:
// app/code/Vendor/Module/Model/Singleton.php
class Singleton {
private static $instance;
private function __construct() {
// Private constructor to prevent instantiation
}
public static function getInstance() {
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}5. REGISTRY PATTERN:
The Registry Pattern provides a centralized place to store shared objects or data. In Magento 2, the registry is a global container for storing variables and objects that need to be accessible across different parts of the application. It allows for a convenient way to share information without relying on global variables.
Example:
// Storing value in registry
\Magento\Framework\Registry::register('key', $value);
// Retrieving value from registry
$value = \Magento\Framework\Registry::registry('key');
6. PROTOTYPE PATTERN:
The Prototype Pattern involves creating new objects by copying an existing object, known as the prototype. While not explicitly implemented in Magento 2, the concept of cloning objects is used in certain scenarios to create copies of existing objects.
Example:
// app/code/Vendor/Module/Model/Item.php
class Item implements \Magento\Framework\CloneableInterface {
public function __clone() {
// Implement cloning logic
}
}7. OBJECT POOL PATTERN:
The Object Pool Pattern manages a pool of objects, providing a way to reuse and manage resources efficiently. In Magento 2, this pattern may be used in scenarios where creating and destroying objects frequently is resource-intensive, and reusing existing objects improves performance.
Example (simplified):
// app/code/Vendor/Module/Model/ObjectPool.php
class ObjectPool {
private $objects = [];
public function getObject() {
if (empty($this->objects)) {
return new MyObject();
} else {
return array_pop($this->objects);
}
}
public function releaseObject(MyObject $object) {
$this->objects[] = $object;
}
}8. ITERATOR PATTERN:
The Iterator Pattern provides a way to access elements of an aggregate object sequentially without exposing its underlying representation. Magento 2 uses iterators in various contexts, such as collections, to traverse and manipulate sets of objects.
Example:
// app/code/Vendor/Module/Model/ItemCollection.php
class ItemCollection implements \IteratorAggregate {
private $items = [];
public function add(Item $item) {
$this->items[] = $item;
}
public function getIterator() {
return new \ArrayIterator($this->items);
}
}9. LAZY LOADING PATTERN:
The Lazy Loading Pattern defers the loading of an object until it is actually needed. In Magento 2, lazy loading is often employed using proxies, where an object is created only when a specific method is called, improving performance by loading resources on demand.
Example (using proxy):
// app/code/Vendor/Module/Model/Item.php
class Item extends \Magento\Framework\Model\AbstractModel {
public function getRelatedData() {
// Lazy loading using proxy
return $this->_getData('related_data');
}
}10. SERVICE LOCATOR PATTERN:
The Service Locator Pattern provides a centralized point for registering and locating services within a system. In Magento 2, the Object Manager acts as a service locator, responsible for creating and managing instances of objects, facilitating a centralized mechanism for dependency resolution.
Example:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$myService = $objectManager->get('My\Custom\Service');11. MODULE PATTERN:
The Module Pattern is an architectural pattern that promotes modularity by encapsulating related functionality into separate modules. In Magento 2, each feature or functionality is encapsulated within a module, allowing for better organization, maintainability, and reusability.
Example:
<!-- app/code/Vendor/Module/etc/module.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vendor_Module" setup_version="1.0.0">
<!-- Module configuration -->
</module>
</config>12. OBSERVER PATTERN:
The Observer Pattern is used for event handling, where an object (observer) subscribes to and listens for events triggered by another object (subject). Magento 2 extensively uses observers for decoupled and extensible event-driven architecture, allowing customizations without modifying core code.
Example:
<!-- app/code/Vendor/Module/etc/events.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="some_event">
<observer name="custom_observer" instance="Vendor\Module\Observer\CustomObserver" />
</event>
</config>// app/code/Vendor/Module/Observer/CustomObserver.php
class CustomObserver implements \Magento\Framework\Event\ObserverInterface {
public function execute(\Magento\Framework\Event\Observer $observer) {
// Observer logic
}
}13. SERVICE CONTRACT DESIGN PATTERN:
The Service Contract Design Pattern defines a clear and standardized API for a module, promoting interoperability and versioning. In Magento 2, service contracts are used to define interfaces for modules, ensuring a consistent and stable contract between different components.
Example:
// app/code/Vendor/Module/Api/MyInterface.php
interface MyInterface {
public function myMethod();
}14. OBJECT MANAGER:
The Object Manager is a key component in Magento 2 responsible for creating, configuring, and managing objects. It acts as a central hub for dependency injection, allowing for the instantiation of objects and resolving dependencies throughout the application.
Example:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$myObject = $objectManager->create('My\Custom\Object');15. INJECTABLE OBJECTS / NON-INJECTABLE OBJECTS:
Magento 2 introduces the concept of injectable and non-injectable objects. Injectable objects can have dependencies automatically injected through constructor injection, promoting better testability and maintainability. Non-injectable objects may be instantiated directly or through the Object Manager.
Example (Injectable):
// Constructor injection
public function __construct(\Magento\Catalog\Model\Product $product) {
$this->product = $product;
}Example (Non-Injectable):
// Direct instantiation
$product = \Magento\Framework\App\ObjectManager::getInstance()->create(\Magento\Catalog\Model\Product::class);16. DEPENDENCY INJECTION:
Dependency Injection is a design pattern where the dependencies of a class are provided from the outside rather than created within the class. In Magento 2, dependency injection is widely used to inject dependencies into constructors, making the code more modular, testable, and adhering to the principles of Inversion of Control (IoC).
Example:
// Constructor injection
public function __construct(\Magento\Catalog\Model\Product $product) {
$this->product = $product;
}17. FACTORY PATTERN OR FACTORY CLASSES:
The Factory Pattern involves creating objects without specifying the exact class of the object that will be created. In Magento 2, factory classes are commonly used to create instances of objects, especially models, providing a level of abstraction for object instantiation.
Example:
// app/code/Vendor/Module/Model/ItemFactory.php
class ItemFactory {
protected $objectManager;
public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager) {
$this->objectManager = $objectManager;
}
public function create(array $data = []) {
return $this->objectManager->create('Vendor\Module\Model\Item', $data);
}
}18. PROXY PATTERN:
The Proxy Pattern involves creating a placeholder for another object to control access to it. In Magento 2, proxies are often used for lazy loading, where an object is loaded only when a specific method is invoked, allowing for efficient resource utilization.
Example:
// app/code/Vendor/Module/Model/Item.php
class Item extends \Magento\Framework\Model\AbstractModel {
public function getRelatedData() {
// Lazy loading using proxy
return $this->_getData('related_data');
}
}