Magento 2, a popular e-commerce platform, extensively uses various design patterns to ensure a robust, scalable, and maintainable architecture. Here are some key design patterns used in Magento 2:
1. Factory Pattern
Factories in Magento 2 are used to create instances of objects without specifying the exact class of the object that will be created. This is useful for creating objects that are needed frequently throughout the application.
$object = $this->objectManager->create(\Vendor\Module\Model\ClassName::class);
2. Singleton Pattern
The singleton pattern ensures that a class has only one instance and provides a global point of access to it. Magento’s configuration and object manager are examples of the singleton pattern.
$config = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\App\Config\ScopeConfigInterface');
3. Factory Method Pattern
Factory methods are used to create various related objects without specifying the exact class of the object that will be created. Magento uses factory methods for creating models.
$productFactory = $this->_objectManager->create(\Magento\Catalog\Model\ProductFactory::class);
$product = $productFactory->create();
4. Observer Pattern
Observers allow for a loosely coupled way of handling events in Magento 2. Modules can observe events and react to them without modifying the core code.
<!-- app/code/Vendor/Module/etc/events.xml -->
<event name="controller_action_predispatch">
<observer name="vendor_module_observer" instance="Vendor\Module\Observer\ObserverName" />
</event>
namespace Vendor\Module\Observer;
use Magento\Framework\Event\ObserverInterface;
class ObserverName implements ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer)
{
// Event handling logic
}
}
5. Dependency Injection (DI)
Magento 2 extensively uses dependency injection to manage class dependencies. This pattern helps in creating a more decoupled and testable codebase.
namespace Vendor\Module\Model;
class CustomClass
{
protected $logger;
public function __construct(\Psr\Log\LoggerInterface $logger)
{
$this->logger = $logger;
}
public function logMessage()
{
$this->logger->info('This is a log message.');
}
}
6. Service Contracts
Service contracts (interfaces) define public methods for a module’s business logic. This pattern provides a clear API and promotes interface use over implementation.
namespace Vendor\Module\Api;
interface CustomInterface
{
/**
* Retrieve custom data.
*
* @param int $id
* @return \Vendor\Module\Api\Data\CustomDataInterface
*/
public function getCustomData($id);
}
7. Strategy Pattern
Magento 2 uses the strategy pattern to choose a specific algorithm at runtime. For example, different price calculation methods can be selected based on configuration.
namespace Vendor\Module\Model;
class PriceCalculator
{
protected $strategy;
public function __construct(\Vendor\Module\Api\PricingStrategyInterface $strategy)
{
$this->strategy = $strategy;
}
public function calculate($product)
{
return $this->strategy->calculate($product);
}
}
8. Repository Pattern
Repositories provide a way to encapsulate the logic required to access data sources. They act as a middle layer between the data source and the business logic.
namespace Vendor\Module\Model;
class CustomRepository implements \Vendor\Module\Api\CustomRepositoryInterface
{
protected $customFactory;
public function __construct(\Vendor\Module\Model\CustomFactory $customFactory)
{
$this->customFactory = $customFactory;
}
public function getById($id)
{
$custom = $this->customFactory->create();
return $custom->load($id);
}
}
9. Proxy Pattern
Proxies are used to defer the loading of an object until it is needed. This can help in improving performance by avoiding unnecessary object instantiations.
namespace Vendor\Module\Model;
class CustomClass
{
protected $logger;
public function __construct(\Vendor\Module\Logger\CustomLogger $logger)
{
$this->logger = $logger;
}
public function logMessage()
{
$this->logger->info('This is a log message.');
}
}