The Proxy Pattern

The Proxy pattern creates an interface giving access to a resource to hide any underlying-complexity as well as to add improvements of the underlying code. The proxy interface looks like the interface it “caches.”

Let’s think about a query object we want to use to query a database. It is great to log any request for debugging purpose.

public class SimpleQuery<T> implements Query<T> {

   public T findBy(String id) { 
       // connect to database, query, etc.
       return db.query(sql);
   }

   public void insert(T object) {
       // connect to database, create id, etc.
       db.insert(sql);
   }
}

We are going to proxy this with inheritance. It is possible to implement this pattern with other techniques such as composition (having a reference of the object to proxy), or introspection if we want the proxy to be dynamic (done at runtime).

public class ProxyQuery<T> extends SimpleQuery<T> {

   private Logger logger = ... // whatever framework you want to use
   
   public T findBy(String id) {
     // connect to database, query, etc.
     String sql = "select * from table where id="+id;
     logger.debug(sql);
     return db.query(sql);
   }

   public void insert(T object) {
     // connect to database, create id, etc.
     String sql = "insert into table (id, value) values ("+id+","+object+")";
     logger.debug(sql);
     db.insert(object);
   }

}

And that’s all! Of course proxies can be much more complex. It can be used to call a remote object. It can be used to use a cache, etc.

Now you may wonder: what is the difference between the proxy pattern and the decorator pattern?

  • The proxy pattern provides an identical interface while the decorator provides an enhanced interface.
  • The decorator usually aggregates (composition) what it is decorating. The proxy does not have to work that way.
  • Proxy might interface an object that has not been created yet. For example, you may want to stack up / validate information before creating the actual object for performance sake.

The Flyweight Pattern

The flyweight pattern seeks to avoid redundancy when storing data. It is a space optimization technique that uses less memory by storing data from similar objects.

Let’s say we want to render the movements of an animal on map based on GPS coordinates collected every 10 seconds from an implanted GPS device. The data collected are represented by a list of GpsPoint:

public class GpsPoint {
  private double longitude;
  private double latitude;
  private double altitude;

  // getters/setters
}

Now we may want to track multiple animals on a single map. The number of points can quickly increase. We can use a buffer to keep in memory duplicated points. Indeed, the animal may stay or go back to the same spots. Our buffer can be very simple:

public class Buffer<GpsPoint> {

   private List<GpsPoint> points;

   public boolean contains(GpsPoint point) {
      return points.contains(point); // assume GpsPoint overrode equals() and hashcode()
   }

   // ...
}

We would need a buffer manager or the renderer can manage the buffer. For example, it would check if the point exists in the buffer before adding it:

public class Renderer {

   private Buffer<GpsPoint> buffer;

   public void render(GpsPoint point) {
       if (!buffer.contains(point)) { // does not keep duplicate in memory
          buffer.add(point);
       }

       buffer.forEach(pt -> drawPoint(pt)); // render each point of the buffer
   }

}

Buffer has less points than what the trace has. Simple technique… the most complicated part of this pattern is probably its name 🙂

The Facade Pattern

The Facade Pattern exposes several components through a single interface. The goal is to simplify the API for the client components.

Let’s say we want to make a robot. A robot is made out of different parts. Our code may look like:

public class SimpleArm implements Arm {

  public SimpleArm() {
  }

}

public class Robot {

   private Arm arm;

   public Robot(Arm arm) {
     this.arm = arm;
   }

   public void moveArm() {
     ...
   }
}

Now this code looks simple, but it could be more complex if the Arm is complicated to be instantiated… and if we add more parts to our robots that are configurable. And we can even have a complex robot made of other robots. Instead of forcing the client code to create the different parts and “assemble” them in the Robot class, we can offer a facade class that requires only a few parameters, instantiate the different parts and offer simple methods to move the robot. The only disadvantage is the possible lack of flexibility for optimization and specification.

The Decorator Pattern

The idea is to augment an existing class with new functionalities without rewriting the existing code. There are two possibilities to do it:

Solution 1: Inherit if the class is not final.

Solution 2: Add a decorator class using composition.

Let’s say we want to program a draw shapes. We can create a Display interface that will be implemented by all of our classes.

public interface Display {

  public void draw();

}

Our basic class draws the shape

public class SimpleDisplay implements Display {

   public void draw() {
     // draw shape
   }

}

Now we want to fill the shape. We can extend what SimpleDisplay does with another class:

public class FillerDisplay {

   private Display display;

   public FillerDisplay(Display display) {
     this.display = display;
   }

   public void draw() {
     fill();
     display.draw();
   }

}

We can also add a zoom effect:

public class ZoomDisplay {

   private Display display;

   public ZoomDisplay(Display display) {
     this.display = display;
   }

   public void draw() {
      zoom();
      display.draw(); 
   }

}

So we can combine those decorators to obtain the result we want:

// a simple display
Display simple = new SimpleDisplay();

// a display filling the shape
Display fill = new FillerDisplay(new SimpleDisplay());

// a display that can zoom
Display zoom = new ZoomDisplay(new FillerDisplay(new SimpleDisplay()));

Notice we do not have to have a filler. A display can simply draw a shape and zoom. There are also ways to simplify the creation of the objects.

What can be trickier is accessing methods in one of the layers. For example, we can imagine that we want the FillerDisplay to use an image to fill the shape. In that case, we would add a method called setImageBackground() but it would be specific to FillerDisplay. To access that method, we would need to implement a getDisplay() in each layer, and we would have a code that looks like:

display.getDisplay().getDisplay()... getDisplay().setImageBackground(img)

which is not … very pretty … (Coding is art after all). What’s possible is to create a “shortcut” method in the client code if it is used frequently:

private Display getFillerDisplay() {
   return display.getDisplay().getDisplay()... getDisplay();
}

It can be lengthy code if each display is a generic:

LayerDisplay<ZoomDisplay<FillerDisplay<RandomDisplay<SimpleDisplay>>>>> display;

hmmm… so good. 🙂

The Composite Pattern

The Composite Pattern creates a mechanism for trading individual objects and compositions of objects in a uniform manner.

What the heck is this definition!?? This is why programming sounds crazy for some. It is sometimes difficult to define programming concepts simply and concisely.

What this composite pattern seeks to do is to handle objects that are composed of other “similar” objects. It is actually very simple. Simply think of a tree of objects with the same behavior. Let’s say we want to know how much each employee, manager, and branch of a bank manages.

public class Employee {  // Leaf
   public double calculatePortfolio() { ... }
}

public class Manager {  // Composite
   private List<Employee> employees;
   private List<Managers> managers; // a manager can manage other managers
   public double calculatePortfolio() { 
     return employees
     .stream()
     .reduce((e1, e2) -> e1.calculatePortfolio() + e2.calculatePortfolio())
     + managers
     .stream()
     .reduce((e1, e2) -> e1.calculatePortfolio() + e2.calculatePortfolio())
   }
}

public class Branch { // Other composite or component
  private List<Manager> managers;
  public double calculatePortfolio() {
    return managers
     .stream()
     .reduce((e1, e2) -> e1.calculatePortfolio() + e2.calculatePortfolio())
  }
}

By calling the calculatePortfolio method, we are able to get the amount of money managed at each level of the tree.

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;
}