paint-brush
Uncover the Alias Patternby@raffaeleflorio
1,410 reads
1,410 reads

Uncover the Alias Pattern

by Raffaele FlorioMay 11th, 2022
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

The Alias pattern deals with two issues. The first one is extending the way a final class builds its objects. The second one is having many constructors with same parameters but different semantic. While doing it, it promotes object composition over inheritance. Indeed, it doesn't require subclassing neither changing the code of the affected class. At a certain degree, it can be seen as a way to decorate objects construction.

Company Mentioned

Mention Thumbnail
featured image - Uncover the Alias Pattern
Raffaele Florio HackerNoon profile picture


While I write OOP code I apply some practices of Elegant Objects.


One of them is that classes should be final. This means that they cannot be extended through inheritance but only through composition.


The advantage is simplicity. I mean that, in this way, each object is seen as a cohesive block. What interest to its clients is its exposed behaviour. Nothing more. Instead, through extension, a client can break it.


For instance, an object can interrelate two of its methods. So, if we can replace through extension one of them we can break the other. For this reason, to be sure, we should check its implementation. In this way we increase coupling between the extended and the extension.


In other words, final classes enforces the idea that we should care only of exposed behaviour. And not of implementation. Nonetheless, it requires a change of how we reason about them. The Alias pattern simplifies an aspect of this change.

Intent

The Alias pattern allows to extend the way a class can build its objects without subclassing or modifying it.

Motivation

Suppose a final class that creates its objects using some mandatory parameters. How can we add another way to create its objects? For instance, how we can add a constructor that use a default value for one or more of its missing parameters?


One approach could be to add another constructor to the class. But this could get out of hand. Furthermore, it could be not possible. For instance, the aforesaid final class could be in an external library.


Another drawback of this approach is that we can pollute the final class. For instance, we can have a final class that builds its objects given a JSON. But after some time we need to add also XML. As you can imagine adding the code to map XML to JSON will pollute inevitably that class.


However, the Alias pattern isn’t limited to final classes. For instance, we cannot have two constructors with same parameters but different semantic.


To resolve this issue we can add static factory methods to the class code. But the same aforesaid drawbacks affects this approach. That is: this gets out of hand; this couldn’t be always possibile; this will pollute the class.


A better approach to both problems is to create another class with the desired constructor behaviour. This class encapsulates its own construction logic. And it will delegate everything to the other class, including the actual creation. This is the Alias pattern.

Applicability

Use the Alias pattern when:


  • You need to add or modify a constructor of a final class;


  • You want to add or modify a constructor of a class without modifying or subclassing it;


  • You need two or more constructor of a class with the same parameters without modifying or subclassing it.

Structure

The structure is simple. We need at least two class that implements the same interface: an Alias and an Aliased.


Participants


  • AnInterface
    • declares an interface.


  • Aliased
    • implements AnInterface;

    • exposes one or more constructors.


  • Alias
    • implements AnInterface;
    • exposes one or more constructors;
    • maintains a reference to an Aliased object;
    • delegates everything to the referenced Aliased object.

Collaboration

  • Alias builds - according to its own rules - an Aliased object and maintains a reference of it. Then it delegates everything to the aliased.


Consequences


The Alias Pattern has the following consequences:


  • It allows adding or modifying constructors easy;
  • It promotes composition over inheritance;
  • It increases the number of classes;
  • It reduces code duplication when used to replace a recurrent creation;
  • Alias classes duplicates delegating code. If this is a problem it could be approach with a base abstract Alias class.

Implementation

To implement the Alias pattern you need:


  1. to define an interface;

  2. to implement the previously defined interface with a class. This will be the aliased one;

  3. to implement the previously defined interface with an alias class, and you need:

    1. to define a constructor that builds an aliased object according some needs;
    2. a private instance variable that reference to the previously built aliased object;
    3. to delegates everything to the aliased object.

Sample Code

The below Java-ish code expresses the Alias pattern. In this code the alias injects a default value for an otherwise mandatory parameter:


interface AnInterface {
  void aMethod();

  Something anotherMethod();
}

final class Aliased implements AnInterface {
  private final A a;
  private final B b;

  Aliased(final A a, final B b) {
    this.a = a;
    this.b = b;
  }
  
  void aMethod() {
    // implementation
  }

  Something anotherMethod() {
    // implementation
  }
}

final class Alias implements AnInterface {
  private final Aliased aliased;

  Alias(final A a) {
    this(
      new Aliased(
        a,
        new InstanceOfB(...)
      )
    );
  }

  private Alias(final Aliased aliased) {
    this.aliased = aliased;
  }

  void aMethod() {
    this.aliased.aMethod();
  }

  Something anotherMethod() {
    return this.aliased.anotherMethod();
  }
}


Related Patterns

At a certain degree, the Alias pattern could be also seen as a way to decorate the objects construction. This vision is especially true if we see a class as an object which responsibility is to create objects.