Magento 2 Must-know Design Patterns for Development Success
Vinh Jacker | 3 days ago
The Most Popular Extension Builder for Magento 2
With a big catalog of 224+ extensions for your online store
Magento 2 Design Patterns can become a beneficial assistant if used correctly. In software programming, design patterns are dispensable support for developers. Everything related to building programs becomes more accessible and organized, reducing much work for the dev team. This article will explore the most essential types of design patterns in Magento 2 to find out what they are and the benefits of using each.
1. Object Manager
Object Manager plays an essential role in Magento 2, replacing the Mage class - a function used to implement and call almost every object in Magento 1. This innovation solves several difficulties with parameter instantiation by establishing a solid connection between the three patterns: object management, dependency injection, and plugins.
Get and Create Methods
Object Manager pattern generates and configures Objects using two main methods: GET and CREATE.
GET:
- Return a singleton object (a class instance that is used to share between multiple components)
- Provide the same response when calling from 2 places
CREATE:
- Return an utterly new class instance
- Provide a new object when calling from 2 places
Object Manager Main Purpose
- Construct and place the class given in the constructor
- Run the singleton pattern
- Control dependencies
- Automatically instantiate parameters
2. Dependency Injection
What is Dependency Injection?
Dependency Injection (DI) is one of the most crucial design patterns for Magento 2 development, built to replace the Mage class in Magento 1 and handle programming dependencies.
Let’s look at this system by separating its name to see what it is.
Dependency:
- Meaning when something depends on another one
- Example: class is dependent on another class/object to perform some functions
Injection:
- Meaning: provide something in a third person
- Example: inject a class into the dependent class Dependency Injection is an object management system used to remove an object’s direct dependency on a class and make objects for that class with a third class.
Magento 2 Dependency Injection
Dependency Injection is made of four following parts:
- Service object: declares dependencies
- Client object: is dependent on the service object and inherits dependencies
- Interface object: determines the ways that the client can use to access the service’s dependencies
- Injector object: performs the dependencies of the service and passes them to the customer’s object
Magento 2 DI can be implemented in 2 ways:
- Via Constructor: Magento\Catalog\Controller\Adminhtml\Product\Save
- Via Method: Magento\Catalog\Api\ProductAttributeManagementInterface
3. Factory
What is Factory?
Factory is another essential aspect among other Magento 2 design patterns. The Factory design pattern in Magento 2 is a non-injectable object that enables the instantiation of representative objects for entities. The Object Manager and business code instantiate it. Magento automatically generates the Factory (located in the “generated” folder) with this type:
Ex: Magento\Catalog\Block\Product\ImageFactory
How to use Factory Design Pattern
- In the Constructor, Call Factory:
function __construct(\Magento\Cms\Model\BlockFactory $blockFactory) { $this->blockFactory = $blockFactory; }
Then, to make a copy of the object, call the create method as follows:
$block = $this->blockFactory->create();
- In case of multiple classes that need some parameters, directly transfer parameters to create:
$resultItem = $this->itemFactory->create([ 'title' => $item->getQueryText(), 'num_results' => $item->getNumResults(), ]);
4. Proxies
To developers, Proxy is one of the most efficient Magento 2 design patterns. It can significantly enhance performance and reduce resource consumption when utilized appropriately. It effectively addresses redundancy issues within a project.
Proxy advantages:
- Simple procedure: only required to declare the “class/Proxy” => the “di.xml” file
- Enhance the program’s performance
- A clear framework, easy to understand
5. Preferences
What are Preferences?
The Preference Design Pattern overrides existing classes and extends business logic. It is crucial to use it appropriately, considering other available design patterns like plugins and observers, which may be more suitable in some instances. Preferences are ideal when alternatives like plugins or observers are not applicable.
There are two ways to manage Preferences in Magento 2:
-
/etc/di.xml (Global) -
/etc//di.xml
Let’s examine an example such as this file: app/code/Mageplaza/Custom/etc/di.xml
<preference for="Magento\Quote\Model\Quote"
type="Mageplaza\Custom\Model\Quote" />
- Class A: Magento\Quote\Model\Quote
- Class B: Bss\Custom\Model\Quote
The next step is to run the loadByCustomer part. At this time, Class B is called as B is required to expand A.
Pros and Cons
Of course, as an alternative to other design patterns, Preferences have different benefits and drawbacks. In details:
Pros:
- Simple to use and declare
- Capable of adjusting most classes in the core
- Able to modify most functions
Cons:
- Conflict with third-party extensions
- Not able to adjust in case of class directly calls via Object Manager
As the advantages of Preference dominated its disadvantages, it’s pretty clear why this pattern is listed among the must-know Magento 2 design patterns.
6. Argument Replacement
What is Argument Replacement?
Argument Replacement is one of the must-know efficient coding techniques when changing constructor argument without affecting other classes. Argument Replacement’s name in the XML file corresponds to the name used in class. For instance, in this file: vendor/magento/module-catalog/etc/di.xml In the constructor of this class: Magento\Catalog\Helper\Product:
Types of Argument
- Object ```
- String
- Boolean
- Number
- Init_parameter
{Constant::NAME}
- Const
…….
- Null
- Array
### Pros and Cons
**Pros**:
- Diverse types to modify the class
- Flexible
**Cons**:
- Complex framework
- Strict structure requirement
## 7. Virtual Types
In Magento 2, Virtual Types provide a way to modify existing classes without impacting other classes or needing to create new class files. They offer the flexibility to inject these Virtual Types wherever they are required.
In other words, Virtual Types can be considered as a sub-class for an existing class.
## 8. Events and observers
Whenever someone wants to modify a class in Magento, events and observers usually come up in their mind. Let’s discuss each one in detail!
### Events
Events can be activated by the module’s action. Notably, events and observers share the same data so that you can change the input data. Additionally, Magento enables us to customize events to modify data.
**Dispatching Events**
To create a new event, utilize the class Magento\Framework\Event\ManagerInterface. The dispatch function within this class can be used to instantiate the desired event name for dispatching.
Code example: https://devdocs.magento.com/guides/v2.3/extension-dev-guide/events-and-observers.html#dispatching-events
**Event Areas**
Events are categorized into three types based on the events.xml file:
- etc/adminhtml/events.xml – adminhtml
- etc/frontend/events.xml – frontend
- etc/events.xml – global
### Observers
We use Observers to catch events and modify input data, allowing for adjustments to logic and more.
**Create an Observer**
To generate a new observer, place your file in the <module-root>/Observer folder and inherit the class Magento\Framework\Event\ObserverInterface.
Code example: https://devdocs.magento.com/guides/v2.3/extension-dev-guide/events-and-observers.html#creating-an-observer
Subscribe events
Utilize the XML file to declare events and observers.
Example: <module-root>/etc/adminhtml/events.xml
After adding the products successfully, it’s likely to move to the execution part of the class AddProductObserver. Then you are free to edit data transmitted through the checkout_cart_add_product_complete event, which already includes request and response.
If you want to turn off events, just insert **disable =“true”** after the observer.
## 9. Plugins
Another approach for customizing a feature in Magento 2 is to use Plugins. The technique can be used on any public method in a class, interface, or framework.
However, it is essential to note that Plugins cannot be applied to the following cases:
- Final method
- Final class
- Non-public method
- Static class method
- __constructor
- Virtual Type
- Objects that are instantiated through Magento\Framework\Interception
So, how can we declare the Plugin? You’re going to need the di.xml file for this.
```
Required elements:
- Type name: Name of class or interface to edit
- Plugin name: Name of the plugin
- Plugin type: Name of the plugin to edit
Optional elements:
- Sort order: Execution order of the plugin
- Disabled: Turn off the plugin
Three ways to use the Plugin method:
- Before: Modify a function’s input data
- Around: Modify a function’s operation process
- After: Modify output data
Pros and Cons:
Pros:
- Clear framework
- Flexible
- Suitable for most public method functions
Cons:
- Incapable of the protected and private method
- Unable to be modified if the class is called directly via Object Manager
10. Repositories
Regarding reading, modifying, or deleting entities, Repositories, and Factories are similar. On the other hand, factories are mainly used for building new entities. Repositories support Soap/Rest API as part of the service contracts- interface.
It’s a bit different when applying these methods:
-
ProductRepository: Returns specified data as defined in the \Magento\Catalog\Api\Data\ProductInterface business code. Unnecessary data will be removed, and cached data will be retrieved from the disk instead of directly from the Model via the database.
-
ProductFactory: Returns model entity’s complete data, including potentially unnecessary information.
In summary, if Repositories meet your requirements, using them instead of Factories is highly recommended.
11. Injectable/Non-Injectable Object
Last but not least, Injectable and Non-Injectable are also crucial Magento 2 design patterns. Let’s get to know more about them!
There are two kinds of Objects in Magento 2 Dependency Injection: Injectable and Non-Injectable. Here are some notes about this pattern:
- Injectable object: singleton objects that can be instantiated and shared by the Object Manager in Magento. These objects can have dependencies on other objects and are typically defined in the di.xml configuration file.
- Non-injectable object: cannot be instantiated by the Object Manager and require manual instantiation. Both of these objects often have a shorter lifespan and may require input data before they can be created.
In reality, most models in Magento are non-injectable objects. Let’s take Product as an example. It actually needs the product ID for transmission.
Conclusion
So, this article has provided a detailed explanation of some of the essential Magento 2 design patterns. While there are more design patterns available, the ones covered here are fundamental to understanding Magento 2 development. By implementing these efficient coding techniques, you can enhance your Magento 2 projects and improve code organization, performance, and maintainability. We hope that this blog has been helpful to you and that you can apply these design patterns successfully in your Magento 2 projects.