The Bridge Pattern

The Bridge Pattern decouples an abstraction from its implementation to enable the two to vary independently. It puts abstraction and implementation in separate class hierarchies. Instead of implementing the abstraction, the “implementation” uses it.

Let’s illustrate it. We want our software to draw maps which are constituted of different shapes (points, lines, polygons, etc.). We could create a Renderer interface with implementations for each shape:

The problem with this design is that we multiply implementations for each shape. To avoid multiplying classes (one of the pattern’s advantages), we can use the bridge pattern:

The bridge is Renderer/Shape

The code would look like:

class Shape {
  private Renderer renderer;
  private int radius;

  public Shape(Renderer renderer, int radius) {
    this.renderer = renderer;
    this.radius = radius;
  }

  public void draw() {
    renderer.drawCircle(radius);
  }
}

// code using the bridge
FlashyRenderer renderer = new FlashyRenderer();
Shape point = new Point(renderer); // which sets the renderer in the class
point.draw();

renderer.updateColor(); // the body of this method may request the shape to re-draw

When to use it?

  • When we multiply classes having the same behavior on similar objects.
  • When abstractions and implementations must be extensible independently.
  • When the implementation must be selected or changed at run-time.
  • When the implementation has no impact on client code.

The Adapter Pattern

When I used to live in France and travel in the US, I had an adapter for my phone charger since the electrical outlets are different: shape, voltage, etc. The Adapter Pattern does the same. It aims to wrap an existing interface to conform it to a required interface.

Let’s consider this company with a CEO, a manager (the “adapter”) and a programmer:

interface CEO { // implementations: bossyCEO, micromanagerCEO, etc. 🙂
  public Demand command();
}

interface Programmer { // implementations: rebelliousProgrammer, etc.
  public void execute(Expectation cmd);
}

interface Manager { // implementations: terrorizedManager, angryManager, etc.
  public void hear(Demand demand);
  public void execute();
}

// adapter class
class SmartManager implements Manager {

  private Programmer programmer; // would not be private if CEO is micromanaging 🙂
  private Project project;

  public SmartManager(Programmer programmer) { // only one programmer 🙂
    this.programmer = programmer;
  }

  public void hear(Demand demand) {
      decrypt(demand);
      discuss(programmer, demand);
      project = plan(demand);
  }

  public void execute() {
    Expectation expectation = project.getPlan();
    programmer.execute(expectation);
  }  
}

The adapter usually wraps the interface it adapts to transform the calls from the consumer interface.

This pattern may require the creation of temporary objects to handle the “adaptation” which impacts performance (time and resources). If it is the case, caching those temporary objects will help.

In our illustration, Project is a temporary object which was created by the plan(Demand demand) method. We could cache project if the CEO has the same demand.

private Map<Demand, Project> plans;

private Project plan(Demand demand) {
  project = plans.get(demand);
  if (project == null) {
     project = ... // create a new project
     plans.add(demand, project); // cache
  }
  return project;
}

The Singleton Pattern

The Singleton Pattern provides only one instance of a class. It is useful when we want to centralize a certain behavior such as querying the database or writing in files.

First, we want to make sure we create only one instance. The basic pattern looks this way:

public class Singleton {

  private static final Singleton INSTANCE = new Singleton();

  private Singleton() {} // not possible to call the constructor from outside the class

  public static Singleton getInstance() {
    return INSTANCE;
  }
}

There are problems with this though. It is possible to create more than one instance by using:

  1. the Reflection API
  2. Serialization. The JVM does not care about the private constructor when serializing/deserializing. To fix this, we just need to add the readResolve method:
protected Object readResolve() {
  return INSTANCE; // return the existing instance instead of creating a new one.
}

For Serializable classes, the readResolve method let us replace/resolve the object read from the stream before it is returned to the caller. By implementing the readResolve method, a class can directly control the types and instances of its own instances being deserialized.

Second, we want to guarantee a lazy initialization. We want to make sure we only create the instance when we need it. It can be as simple as:

publics static Singleton getInstance() {
  if (instance != null) {
    instance = new Singleton();
  }
  return instance
}

Third, we want to guarantee thread safety. In the previous case, if there are multi-threads and they access the method at the same time, they may create their two instances (one for each thread). It is possible to create an inner static Singleton using a nested class:

class Singleton {

  private Singleton() {}

  // Nested class 
  private static class Builder {

     private static final Singleton INSTANCE = new Singleton();

     public Singleton getInstance() {
       return Builder.INSTANCE;
     }
  }
}

It is also possible to use enum instead of class. Using an Enum solves the issue with the Reflection API, but it does not allow you to persist an internal state through serialization despite the fact that all the enum are serializable. For example:

public enum Singleton {
  INSTANCE; // name of the enum
  
  Singleton() { // Constructor is always private
    // constructor if needed
    myState = "VALUE"; 
  }

  private String myState;
  public void setValue(String myState) {
    this.myState = myState;
  }
}

If you set the value of myState before serializing the enum, the deserialization will return to the default value set in the constructor which is here “VALUE.” This is a possible limitation for using enum (as well as the impossibility to create subclasses).

Good tips about using a singleton

  • When to use a singleton? For example, we want to create a class that manages displaying maps. Should I use a singleton or a regular class? It seems it could be a singleton. A few questions can help decide:
    • Does the instance access resources that are shared?
    • Should we limit the creation of this class to only one instance? (What if we want to create another map section?)
    • Is it worth the effort to make it thread safe?
  • How to handle resources in the Singleton? A good idea is to use the principle of dependency injection to be able to test the Singleton as well as making sure it is adaptable. Let’s illustrate it quickly with a singleton managing database connections:
enum dbConnector {
  INSTANCE;
  ... // constructor

  public Connection getConnection() {
    DB database = new DB("Oracle"); // hardwire dependency
    return database.getConnection();
  }
}

We can inject the dependency to the database:

enum dbConnector {
  INSTANCE;
  ... // constructor

  public Connection getConnection(DatabaseManager dbMgr) {
    DB database = dbMgr.get("Oracle"); // the dependency is injected
    return database.getConnection();
  }
}

The Prototype Pattern

The Prototype Pattern has purpose to simplify the creation of complex objects by copying them. An existing (partially or fully constructed) design is a Prototype. Let’s illustrate this with a Recipe object:

class Recipe {
  List<String> ingredients;
  List<String> utensils;
  int timeToPrepare;
  int timeToCook;

  ...
}

Let’s say we want to create a bunch of cake recipe. We want to create a basic recipe that can be completed later:

Recipe prototypeCake = new Recipe();
prototypeCake.addIngredient("Flour");
prototypeCake.addIngredient("Eggs");
...
prototypeCake.addUtensil("Bowl");
prototypeCake.addUtensil("Mixer");
...

Now time for the most complex part of the pattern: cloning the prototype. It requires to deep copy every single property (when needed).

class Recipe {
   ...

   public static Recipe clone(Recipe toClone) {
      Recipe copy = new Recipe();
      copy.timeToPrepare = toClone.timeToPrepare;
      copy.timeToCook = toClone.timeToCook;
      toClone.ingredients.forEach(copy::addIngredient);
      toClone.utensils.forEach(copy::addUtensil);
   }
}

// The creation of other recipes becomes much easier
Recipe chocolateCake = Recipe.clone(prototypeCake);
...
Recipe strawberryCake = Recipe.clone(prototypeCake);
...
Recipe cheeseCake = Recipe.clone(prototypeCake);
...

The difficulty with cloning is the to figure out how to copy the whole tree of objects that is needed. What if the list of ingredients was not a list of String but of Ingredient objects?

List<Ingredient> ingredients;

class Ingredient {
  double quantity;
  String description;
  Quality quality;
  double price;
  ...
}

We would need to deep copy Ingredient, and Quality, etc… Another way to clone is to use Java’s serialization mechanism which allows to copy the whole tree of objects by values.

So now, we can customize the objects:

chocolateCake.addIngredient("Chocolate");
etc...

Java Generics and Type Safety

When I learned to code in Java, there was no such thing as generics to ensure type safety. Casting objects was part of the routine, and CastClassException was a familiar message. But Java now comes with Generics to help us avoid those runtime exceptions (when the application runs). Generics look like MyClass. Instead of having runtime exceptions, the compiler shows errors. Generics specify the type of what is within a container class (in this case MyClass). For example, we can define Cart to represent a cart of product from a shopping website.

Here are a few guidelines to use them:

1. Avoid using raw type. It is only there for backward compatibility. If necessary, use unbounded wildcards.

Cart cart; --> raw type: No!
Cart<?> cart; --> Unbounded wildcard type: Better!
Cart<E extends Item> --> Bounded type parameter: Better!
Cart<Item> cart; --> Generic: Better!

Wildcards are useful to ensure type safety even when the type is unknown. However, we cannot assume the type of object that we get out of our container… and we cannot put any element (other than null) into our container. If these restrictions are unacceptable, we can use generic methods or bounded wildcard types.

Cart<?> cart = Cart.empty();
cart.add(something); --> do not compile
Object something = cart.get(0); --> cannot assume the type of something

Unbounded wildcards are ok when nothing specific to the element type is used. For example, list.size() does need to know the type of objects in the list.

If for whatever reason, you use a raw type, a good practice is to test before with instanceof or isAssignedFrom.

2. Remove unchecked warning. If for whatever reason, you use raw types or cast such as:

Set<E> exaltation = new HashSet();
Set exaltation = new HashSet<>();

Add @SuppressWarnings(“unchecked”) on the smallest scope possible. For example, add the annotation on a method instead of a whole class. Otherwise, it will mask warnings you need to see. Also comment to explain why it is safe.

3. Use generic types – obviously – whether generic classes or methods. A static method can even be generic:

static <E> List<E> asList(E[] a)

However, a generic class cannot infer a static method, which means that:

class Cart<E extends Item> {
   public add(E item) {
     // E must extend Item because of the class declaration
     …
   }

   public static <E> List<E> asList(E[] a) {
     // E here does not depend from the class declaration.
     // the solution is: <E extends Item> static List<E> asList(E[] a)
     …
   }
}

4. Use bounded wildcard to add flexibility. Bounded wildcards look like: Iterable. It specifies the possible boundaries of the parameters. Let’s illustrate this. We want to create a Cart class:

public class Cart<E> {
   public Cart();
   public void add(E e);
   public E pop();
   public boolean isEmpty();
   public void addAll(Iterable<E> src) {
      for (E e : src)
         add(e);
      }
   }
}

Cart<Item> cart = new Cart<>();
Iterable<Fruit> fruits = … ; // Fruit extends Item
cart.addAll(fruits); // Won't work because Iterable<Fruit> cannot be converted to Iterable<Item>

The solution is:

public void addAll(Iterable<? extends E> src)

Use wildcard types on input parameters. Avoid bounded wildcard types as return types. Instead of providing flexibility, it would force you to use wildcard types in client code. You should not need to think about wildcards in the client code. If you have to return a wildcard, remember: Wildcards means “anything” so treat it that way. It implies you do not need to know what is manipulated. For example:

Cart<?> getCart();

It may be ok if what you do is simply call methods on the Cart object that can be type agnostic, such as getting the total sum of the cart:

Cart<?> cart = getCart();
double sum = cart.getSum(); // does not depend on the type of product in the cart

if a type parameter appears only once in a method declaration, replace it with a wildcard. If it’s an unbounded type parameter, replace it with an unbounded wildcard; if it’s a bounded type parameter, replace it with a bounded wildcard.

Generics are great, but it can quickly get messy with polymorphism… but this is for another post.

The Abstract Factory Pattern

“Abstract Factory” sounds barbarian… and I have seen a few variants. It was sometimes confusing and unclear.

The Abstract Factory pattern implements the dependency of injection principle for polymorphic objects. It reverses the responsibility to create objects from the object itself to another one called Factory. For example, we want to create a list of objects representing a mathematical operation.

// parent class
class Operation {
   public double operate(double x, double y);
}

A class can chain operations to sum up the results of each operation:

class Operator {
  
  public double perform(List<Operation> ops, double x, double y) {
 
    double res = 0;
    for (Operation op : ops) { // new style
       res += ops.operate(x, y)
    }
  }

}

Now we can have many different operations:

class Sum extends Operation {
   public double operate(double x, double y) {
     return x + y;
   }
}

class Minus extends Operation {
   public double operate(double x, double y) {
     return x - y;
   }
}

class Multiply extends Operation {
   public double operate(double x, double y) {
     return x * y;
   }
}

class Divide extends Operation {
   public double operate(double x, double y) {
     return x / y;
   }
}

These operations can be constructed following the abstract factory pattern. It is called “abstract” because it relies on at least an abstract parent that is implemented by concrete factories depending on what is needed to be created.

interface OperationFactory {
  Operation createOperation();
}

class SumFactory implements OperationFactory {
  Operation createOperation() {
     return new Sum();
  }
}

class MinusFactory implements OperationFactory {
   ...
}

etc.

// we need something (constructor, provider class, or inner builder class, etc.) to construct the factories
class FactoryProvider {
  public OperationFactory getFactory(String type) {
    switch (type)
       case "sum" :
          return new SumFactory();
       case "minus" :
          return new MinusFactory();
       ...
  }
}

The abstract factory pattern matches the factory polymorphism with the classes’ polymorphism.

It is obviously unnecessary in this case, but it would make more sense if we want to accomplish something more complex, such as creating different Operators with different Operations. Operator could perform operations by sub-operators. In that case, we may have something like:

interface OperatorFactory {

   Operator buildOperator();
   Operation buildOperation();
   Operator buildInterOperationOperator(); // operator performing an operation between different operations (other than simple sum as done previously), etc.
   Operation buildInterOperation();

}

class DistanceCalculatorFactory implements OperatorFactory...
class PowerFactory implements OperatorFactory...
class AbsoluteFactory implements OperatorFactory...

The Faceted Builder Pattern

The Faceted Builder Pattern is a sub pattern of the builder pattern. Its purpose is to clarify the construction of a complex object “fluently.” Let’s say we want to build a User object with its personal data (personal info, address, education and education). This pattern enables us to have this:

User user = new UserBuilder()
   .called()
      .firstname("Matthew")
      .middlename("Fred")
      .lastname("Dupont")
   .lives()
      .address("123 rue de la pomme")
      .city("Montauban")
      .postalcode(42331)
      .state("Occitanie")
      .country("France")
   .studied()
      .elementary("Ecole Municipal de Paul Laffort")
      .middleschool("College Pourvoira")
      .highschool("Le Bac de Demain")
      .university("Polytechnique")
   .build();

The idea is to define a UserBuilder class that will have three subclasses: UserInfoBuilder, UserAddressBuilder, UserEducationBuilder:

class User {
  // all fields here...
  private String firstname;
  private String lastname;
  ...

  User(UserBuilder builder) {
    this.firstname = builder.firstname();
    ...
  }

}

class UserBuilder {
   public UserInfoBuilder called() { // return info builder to set info
      ...
   }

   public UserAddressBuilder lives() { // same for address
      ...
   }

   public UserEducationBuilder studied() { // same for education
      ...
   }

   public User build() {
     return new User(this);
   }
}

// since UserInfoBuilder extends UserBuilder, we can call lives()
// or studied() once we are done setting up the personal info
class UserInfoBuilder extends UserBuilder { 

   private String firstname;
   ...

   public UserInfoBuilder firstname(String firstname) {
      this.firstname = firstname;
   }
   public UserInfoBuilder middlename(String ...) // same
   public UserInfoBuilder lastname(String ...) // same
}

class UserAddressBuilder extends UserBuilder {
   private String address;
   public UserAddressBuilder address(String address) {
      this.address = address;
   }
   public UserAddressBuilder city(...) // same
   public UserAddressBuilder postalcode(...) // same
   ...
}

class UserEducationBuilder extends UserBuilder {
   ...
   public UserEducationBuilder elementary(...) {
      ...
   }
   
   ...
}

That’s all!

The Design Pattern Gamma Categorization

Design patterns are usually categorized in three categories:

Creational Patterns

  • Manages construction of objects
  • Can be explicit (ex: constructors) or implicit (ex: Dependency Injection, reflection, etc.)
  • Single statement vs step-by-step process

Structural Patterns

  • Focuses on relationships between objects. They seek to define structures.

Behavioral Patterns

  • Focuses on communications between objects.
  • Deals with assigning responsibilities, encapsulating behavior, delegation, etc.

A pattern can belong to more than one category. A design pattern usually focuses on one main issue and proposes a solution that offers flexibility (easy to maintain and to improve) and reusability.

SOLID* Design Principles (by Robert C. Martin)

Single Responsibility Principle (SRP) / Separation of Concerns

A class is responsible for doing only one thing. Why? The code is cleaner, easier to maintain, and reusable. For example, instead of having a class storing data and persisting it in a file, we can create two classes: a store class and a persistence class.

Open-Closed Principle (OCP)

A class should be open for inheritance, but closed for modification. For example, we want to create a chef class that can make meals. We could define methods like makePizza(), makeCurry(), etc. but it would violate the OCP. Each time, we would need to modify the chef class each time we need to add a new type of meal. A better design would be:

class Chef() {
   Meal make(pizza, recipe);
}

In this case, we do not need to modify chef if we want another type of meal. We would simply give a different recipe. We can also extend Chef if we want to have a FasterChef or FancyChef, etc.

Liskov Substitution Principle (LSP)

A parent class should be substitutable by a subclass. Or according to Barbara Liskov – which is clearer to me :

Let Φ(x) be a property provable about objects x of type T. Then Φ(y) should be true for objects y of type S where S is a subtype of T.

Why? to guarantee that the subclass follow the same behavior as its parent, and to avoid introducing bugs by overriding methods.

class Car() {
   boolean engineOn; // default value = false

   void turnKey() {
     engineOn = true;
   }

   void start() {
      turnKey();
   }

   boolean isOn() {
     return engineOn;
   }
}

class Ferrari() extends Car {
   void start() {
     pressButton(); // no key
   }
   ...
}

class Driver() {
   void use(Car car) {
      car.start();
      if (!car.isOn()) {
        System.out.println("Not working...") 
      }
   }
}

driver.use(ferrari) -> would write "Not working..." because the subclass does not extend its parent's behavior properly which means it is not substitutable.

Interface Segregation Principle (ISP)

An interface must only include methods defining a specific behavior. Or in other words: YAGNI = You Ain’t Going to Need It! Why? to avoid unclear and unimplemented methods when not needed.

Let’s say we want to create a Car interface:

public interface Car {
  void start();
  void drive();
  void removeSeats();
}

This interface may work for a MiniVan class, but not for a Coupe:

public class MiniVan implements Car {
  void start() {
    // do something
  }

  void drive() {
    // do something
  }

  void removeSeats() {
    // do something
  }
}

public class Coupe implements Car {
  void start() {
    // do something
  }

  void drive() {
    // do something
  }

  void removeSeats() {
    // do NOTHING! --> cannot remove seats in a coupe
  }
}

It is better to define two interfaces defining its own behavior:

public interface Drivable {
  void start();
  void drive();
}

public interface Expandable {
  void removeSeats();
}

// As result, we have:
public class MiniVan implements Drivable, Expandable ...
public class Coupe implements Drivable ...

Dependency Inversion Principle (DIP)

This principle (not to be confused with dependency injection) has two parts:

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

B. Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.

The purpose is to avoid dependency from high-level modules on low-level modules. Otherwise, changes on those low-level modules imply refactoring high-level modules. In summary:

High-Level modules -> Interfaces/Abstractions -> Low-Level modules

Let’s say we want to write a reader class (high-level) that represents someone who reads a book.

class Reader {
  private Book book;
  private int currentPage;

  void openBook(Book book) {
     this.book = book;
     this.currentPage = book.open();
  }

  void read() {
     String text = book.readPage(currentPage);
  }

  void turnPage() {
     currentPage++;
     book.gotToPage(currentPage);
  }

}

This class relies on a Book class (low-level):

class Book {
  int open() { ... }
  String readPage() { ... }
  void goToPage() { ... }
}

Now, what happens if instead of a book, our reader wants to read a PDF? or a eBook? or anything else that is readable? We would need to refactor our Reader class. A better version of our code would be:

interface Readable { // our abstraction layer between high and low level
   void open();
   String read(int size);
   void goTo(int location);
}

class Reader {
   private Readable material;
   private int location;
   private final int sizeIcanHandle = 1000;

   void openBook(Readable material) {
     this.material = material;
     this.location = material.open();
   }

   void read() {
     String text = material.read(sizeIcanHandle);
   }

   void next() {
     location += sizeIcanHandle;
     material.gotTo(location);
   }
}

Book, eBook, PDF, etc. classes can implement the Readable interface, and Reader would not need to be rewritten.

Now in real life, I have often seen a multitude of interfaces with only one implementation. Of course, one day we may need another implementation, but most of the time, it sits there and we are not going to need another implementation (by the time we do, we may have already been in an effort to rewrite the whole application), or the interface needs rework (because we do not plan well for unknown future) and debugging becomes tedious. I do not mean to say abstractions are useless, but I sometimes wonder about the benefits vs the costs. Do we really need to be “systematic” in our coding approach? Again, coding is a bit artsy, no matter what developers may say…

*Now you should know what SOLID stands for.

The Builder Pattern

The Builder pattern is useful when we want to create objects with many properties to set and to ensure their immutability.
Let’s illustrate this concept. Lately, I have been cooking marinaded meat. But as you can imagine, it is far better to have all the ingredients mixed before marinading the meat.

We could simply use the constructor to do it, but it is lengthy, and possibly difficult to call if not all the ingredients are ready by the time we want to invoke the constructor.

public class Marinade {
  private Ingredient soySauce;
  private Ingredient garlic;
  private Ingredient gingembre;
  private Ingredient brownSugar;
  private Ingredient onion;

  public Marinade(Ingredient soySauce, Ingredient garlic, Ingredient gingembre, Ingredient brownSugar, Ingredient onion) {
    this.soySauce = soySauce;
    this.garlic = garlic;
    this.gingembre = gingembre;
    this.brownSugar = brownSugar;
    this.onion = onion;
  }
}

The other possbility is to use setters.

public class Marinade {
  private Ingredient soySauce;
  private Ingredient garlic;
  private Ingredient gingembre;
  private Ingredient brownSugar;
  private Ingredient onion;

  public Marinade() {
    this.soySauce = soySauce;
    this.garlic = garlic;
    this.gingembre = gingembre;
    this.brownSugar = brownSugar;
    this.onion = onion;
  }

  public void setSoySauce(Ingredient soySauce) {
    this.soySauce = soySauce;
  }

  public void setGarlic(Ingredient garlic) {
    this.garlic = garlic;
  }
  …
}

The problem with setters is that the properties are mutable. In our case, we do not want such a thing. Once our marinade is made, it is too late! Here comes the Builder Pattern.

public class Marinade {
  private final Ingredient soySauce;
  private final Ingredient garlic;
  private final Ingredient gingembre;
  private final Ingredient brownSugar;
  private final Ingredient onion;

  public Marinade(Builder builder) {
    this.soySauce = builder.soySauce;
    this.garlic = builder.garlic;
    …
  }

  public static class Builder() {
    private Ingredient soySauce;
    private Ingredient garlic;
    private Ingredient gingembre;
    private Ingredient brownSugar;
    private Ingredient onion;

    public Builder() {}

    public Marinade build() { 
     return new Marinade(this); 
    } 

   public void soySauce() { 
     this.soySauce = soySauce; 
   } 

   public void garlic() { 
     this.garlic = garlic; 
   } 
   ...
  }
}

In our case, the builder is an inner class. To build a marinade, we simply need:

// also called Fluent Builder/Interface since it returns itself making the construction "fluent"
Marinade marinade = new Marinade.Builder()
    .soySauce(soySauce) 
    .garlic(garlic)
    …
    .build();

Simple and elegant… and the properties are immutable.