Magento 2 has a handful of appealing design patterns intending to make code-reading smoother, developing lighter and optimizing quicker. We know design patterns are usually recyclable solutions to most of our problems during the development and suggested code-writing process.
Design pattern are a unique tool available to us as they are designed to help solve common glitches as seen fit, rather than deploying complicated verbatim implementations.
Magento 2 is equipped with a variety of design patterns such as the following:
- Front Controller
- Object Pool
- Lazy Loading
- Service Locator
- Active Record
- Service Contract
- Object Manager
- Injectable Objects
- Non-injectable Objects
- Dependency Injection
- Factory Pattern or Factory Classes
- Proxy Pattern
I will go over essential points and functionalities of each design pattern mentioned above.
Magento bases itself on an exceptional MVC pattern which uses a configuration layer based on DOM. This causes the configuration application actions to be force-driven by XML in addition to usual Model-View-Controller architecture.
To execute application workflows Magento employs a pattern known as Front Controller. This pattern has one entry point for all requests (index.php).
This particular method is employed to portray classes. In Magento you can portray a class by calling a suitable method transitioning an abstract name which represents a class group after which a class name follows. Class groups and suitable abstractions are stated in XML configuration files. This is located in the module’s folder
This concept draws similarities from Magento class groups and factory class abstraction. A Singleton pattern is expressed for classes and blocks alike.
A registry is mainly a pattern which makes any data or object publicly available on a global scale to be used by any resource.
Prototype is generally applied as an extension of the Magento’s Abstract Factory pattern. It guarantees that a suitable subclass is expressed through suitable types that are allocated to an object.
In simple terms this implies that anytime you want a specific class to be defined through a parent type, this design pattern will come up with the correct class for what you need.
This pattern retains objects ready for repeated use rather than re-instantiating and terminating them once they have filled their purpose. If you’re looking to save on compute cycles and memory consumption, this pattern will be very helpful.
Iterator will let an object navigate through another class’s elements. This design pattern passes multiple diverse sets of data without modifying the original structure allowing the iteration.
With Lazy Loading you can aim to delay object loading until it is called on. Generally in Magento, this design pattern is with data rather than objects.
Service Locator is a pattern that allows its user to achieve a service by covering the process with an abstraction layer. The user can then retrieve a suitable service even if they don’t know what it is at runtime.
This pattern defines a modular programming that highlights that groups a program’s functionality into independent modules that are also interchangeable.
In this kind of pattern, an event listener is placed at a particular point throughout the execution of an application. The application will be permitted to “hook” other components into the event listener and implement their code at this point.
In the database table, objects represent a row. Objects must have properties that show the columns that represent the table’s structure. They should also have methods to modify the respective properties in the database.
The Use of the Patterns by Magento
The classes which inherit after Mage_Core_Model_Abstract class have a right to save(), delete() and load() ways that agree to modifying, creating, deleting or loading records in a table that connects with the class.
Moreover, Mage_Core_Model_Abstract class inherits from Varien_Object, which is responsible for the magical gifts __set() and __get(). These are a blessing if you want to map columns in a database automatically in accordance to a given object’s properties.
All of the above can be used in Magento 1
Service Contract Design Pattern
A modular or extension based system permits third-party developers to overwrite and customize its core framework. And Magneto 2 falls in this type of system. But, obviously, you can find many issues while performing customizations. For example, developers may begin to find it difficult to keep up with external extension customizations.
To counter such issues, Magento has provided us the Service Contract pattern. A service contract is a combination of interfaces that behaves like a layer connecting the business layer to an end user. Meaning, instead of having an end user exposed to business logic customization, a service contract will serve as a layer in between.
Service contracts improves Magento’s modularity. It can help merchants easily upgrade with durable and well-defined API that Magento or other external modules use. Another benefit is how conveniently it uncovers business logic through SOAP or RESTs interfaces.
Object Manager is made up of a number of patterns like:
- Dependency Injection
- Abstract Factory
- And others
However, object manager has a huge role to play which is probably why Magento prevents its direct use. Your object manager is accountable for applying singleton, factory and proxy patterns. It automatically triggers parameter to be incorporated in class constructors.
Injectable & Non-Injectable Objects
Now, before we move on, I believe it’s a good time to understand injectable and non-injectable objects.
These are object that do not have an identity of their own. For example, EventManager or CustomerAccountManagementService.
These are the opposite. They will naturally have an identity, which is why you must know the exact instance you want to work on.
A substitute to Magento 1’s Mage is the Dependency Injection. This concept proves that we can inject a dependent object into an external environment as opposed to actually creating an internal one. Now it’s possible to ask for resource at the time an object is created in comparison to making resources when required. You can simplify future testing and modification by mocking needed objects.
Factory Pattern or Factory Classes
Make layer between the business code and object manager with Factory Classes. You do not need to clearly define Factory Classes as they are generated automatically. For Non-Injectable objects it would be preferred to create factory classes.
Proxy classes work on behalf of another class. Sometimes in Magneto 2 they are used instead of resource hungry classes. By exploring the reason behind occurrence of proxy classes, you will better understand what a proxy class does.
We already know that Magento normally uses constructor injection to create an object. When we portray an object in every class it will also portray in its constructor this leads to a chain of instantiation through the constructor. It affects process and performance by slowing it down greatly. So, to end that chain instantiation, Magento applies proxy classes.
Let’s take a look at this code:
In this code above, we used proxy classes for catalogProductStatus and productLink.
Now we run this command below.
php bin/magento setup:di:compile
You have asked Magento to create proxy classes using di.xml on the fly with a few fixed conventions, which substitutes the former object with a proxy class object.
To understand how it works, let’s examine the proxy class.
Some common convention Magento follow while creating proxy:-Namespace of proxy class will be same as original (Magento\Catalog\Model\Product\Attribute\Source\Status)
Proxy class only extends one object i.e, object managerHas magic functions such as __sleep, __wake which are invoked only on certain action and functionsuch as __clone will make an object of original class and will provide the object only when it isneeded (making use of lazy loading design pattern), thus improving the performance of applicationhttps://devdocs.magento.com/guides/v2.0/extension-dev-guide/proxies.htmlPlugins (Interceptors)
To summarize, an interceptor class, modifies public class function behavior by interrupting a functioncall and implementing a code around, before, or after that function call. This permits extending orsubstituting the performance of original, public methods for any interface or class.
Extensions that aim to intercept and alter public method behavior can make a Plugin class. These are known as plugins.
Interception simplifies and effectively reduces conflicts between various extensions that alter thebehavior of the same method or class.
This interception approach reduces conflicts among extensions that change the behavior of thesame class or method. The class function’s behavior modifies with the class implementation of yourplugin, however it won’t modify the class itself. Interceptors do not conflict amongst each other sincethey can be sequentially called based on a configured sort order.
Plugins cannot be used with any of the following:
– Final methods
– Final classes
– Non-public methods
– Static methods__construct
– Virtual types
– Objects that are instantiated before Magento\Framework\Interception is bootstrappedObjects that are not instantiated by the ObjectManager (e.g. by using new directly). https://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html
Magento application uses object manager to dodge boilerplate code while putting together objectsduring instantiation.
The ObjectManagerInterface achieves an object manager duties in Magento.
The object manager must fill the following responsibilities:
– Creating Objects in proxies and factories
– Implement singleton by reinstate the unchanged shared instance of a class when asked for
– Manage dependency by portraying the preferred class whenever an interface is requested by its constructor
– Automatically portraying parameters in class constructors