Learn About Mixin Pattern

Mixin is an object oriented programming concept that has been used successfully in the enterprise application development scenarios. In an object oriented programming language, Mixin is a class which contains methods from other classes.

Overview

Mixin is an object-oriented programming concept that has been used successfully in enterprise application development scenarios. In an object-oriented programming language, Mixin is a class which contains methods from other classes. Mixin class does not necessarily have to be the parent class of all those other classes. That means, Mixin can be referred to as “included” instead of “inherited”.

Mixin avoids DoD (Diamond of Death)

Mixin brings in the code reusability and can be used to avoid the classic diamond of death problem because of inheritance ambiguity that can be caused by multiple inheritance.

What is Diamond of Death?

Diamond of death refers to the ambiguity that can occur when two classes (example parent1 and parent2) inherit from one base class (base) and another class (Child) inherits from classes parent1 and parent2. Please refer to the below diagram to avoid the confusion around this inheritance.

Mixin Pattern

Suppose, base class contains a method named Display(). Classes paren1 and parent2 overrides the Display() method. However, Child class does not override Display() method. So, when an instance of class Child calls Display() method, which version of the method will be called? parent1 or parent2?

This is referred to as diamond of death issues because of the shape of the inheritance diagram (diamond).

How does Mixin avoid DoD?

Mixin class does not involve any inheritance and can contain methods from other classes. This helps to avoid the diamond of death issue. Although virtual inheritance can address DoD, the alternatives of Mixin can be used effectively. Mixin pattern is very popular in Jthe avaScript community.

Mixin helps to implement Dependency inversion principle

Dependency inversion principle (DIP) is D in SOLID principles and refers to the decoupling of modules.

  1. High-level modules should not directly depend on low-level modules; instead, both should depend upon abstraction.
  2. Abstraction should not depend upon details; instead, details should depend upon abstraction.

Mixin helps us to obey the dependency inversion principle by providing abstraction and helps to inject the dependencies.

Mixin in action

In very simple manner, Mixin can be denoted as below.

Mixin Pattern
Image Courtesy: https://www.safaribooksonline.com

Mixin allows defining a set of functionalities to an object. Mixin class defines distinct functionality. Other classes can then include Mixin class and access its properties and methods.

The Mixin Function

In a simple scenario, class B can extend class A to get its functionality through inheritance. But Instead of class A extending class B, function B can take class A and return new class with the required added functionality. Here, function B is a Mixin function.

A Mixin function,

  1. Takes constructor
  2. Creates a class that extends the constructor
  3. Adds new functionality to the new class
  4. Returns new class

Note
The code sample is written using TypeScript for demonstration purposes.

The simplest form of Mixin function is as follows,

  1. type Constructor<T = {}> = new (...args: any[]) => T;  
  2.   
  3. // A mixin that adds a property  
  4. function Timestamped<TBase extends Constructor>(Base: TBase) {  
  5.   return class extends Base {  
  6.     timestamp = Date.now();  
  7.   };  
  8. }  
  9.   
  10. // a mixin that adds a property and methods  
  11. function Activatable<TBase extends Constructor>(Base: TBase) {  
  12.   return class extends Base {  
  13.     isActivated = false;  
  14.   
  15.     activate() {  
  16.       this.isActivated = true;  
  17.     }  
  18.   
  19.     deactivate() {  
  20.       this.isActivated = false;  
  21.     }  
  22.   };  
  23. }  

We will take a simple example to demonstrate Mixin

Mixin Pattern

Let’s go into the details of each class.

  1. // Base class  
  2. class Person {  
  3.       constructor(public name:string, public age:number){  
  4.       }  
  5.   
  6.       showInfo() {  
  7.             alert(“Name: “ + this.name + “ Age: “ + this.age);  
  8.       }  
  9. }  
  10.   
  11. // First Mixin (A class can implement multiple Mixin)  
  12. class Programmer {  
  13.       Code() {  
  14.             alert(“Programmer.Code”);  
  15.       }  
  16. }  
  17.   
  18. // Second Mixin (A class can implement multiple Mixin)  
  19. class Manager {  
  20.       Manage() {  
  21.             alert(“Manager.Manage”);  
  22.       }  
  23. }  

Now, let us have a library code for Mixin

  1. function applyMixins(derivedCtor: any, baseCtors: any[]) {  
  2.     baseCtors.forEach(baseCtor => {  
  3.         Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {  
  4.              if (name !== 'constructor') {  
  5.                 derivedCtor.prototype[name] = baseCtor.prototype[name];  
  6.             }  
  7.         });  
  8.     });  
  9. }  

This function should be included in a program such that it can be accessed by all Mixins.

Now, let’s implement the actual Employee class using available Mixin by treating them like an interface.

  1. // Child class that inherits/extends from base class and implements multiple classes an Mixins  
  2. class Employee extends Person implements Programmer, Manager {  
  3.       constructor(name, age, public salary: number) {  
  4.             super(name, age); // call base class constructor  
  5.       }  
  6.   
  7.       showInfo() {  
  8.             alert(“Name: “ + this.name + “ Age: “ + this.age + “ Salary: “ + this.salary);  
  9.       }  
  10.   
  11.       Code: () => void  
  12.       Manage: () => void  
  13. }  
  14. applyMixins(Employee, [Programmer, Manager]);  

A few things to consider here,

  • Use the implements keyword, and not extends
  • Have matching signature to compile the code. Implementation will be provided by Mixin
  • Call applyMixins with correct arguments

Let’s test out our Mixin by writing simple test code,

  1. var per: Person = new Person(‘Nanddeep’, 30);  
  2. per.showInfo(); // calls showInfo of Person class  
  3.   
  4. var emp = new Employee(‘Sachin’, 50, 300);  
  5. emp. showInfo(); // calls showInfo of Employee class  
  6.   
  7. emp.Code(); // calls Programmer.Code  
  8. emp.Manage(); // calls Manager.Manage  

Summary

Mixin pattern is useful in object oriented programming to write the code with best practices and follow the SOLID principles.