Showing posts with label Design patters. Show all posts
Showing posts with label Design patters. Show all posts

Sunday, September 21, 2014

Memento design pattern in Java

Recently when recapping my design patterns I came across a Memento. In principle, it provides means for capturing and externalizing an object’s internal state without violating the encapsulation - only the Originator can manipulate the state saved in Memento. That would require a Memento class to implement two interfaces - a wide one for the Originator with appropriate get and set methods and a narrow one for other objects to be able to pass the Memento where necessary.

The GoF book presents one possible implementation of that pattern in C++ using a “friend” class. It defines two classes - an Originator and a Memento. The latter defines two methods marked as private - getState and setState. In addition to that it declares the Originator class as a friend thus letting it access its private members.

As Java being my primary programming language it made me think how we could implement the Memento using it. Especially given the fact that Java does not support the friend class concept.

The most straightforward solution is to put the Memento, its interfaces and the Originator in the same package. The wide interface will be package-private and the narrow one public:
package memento1;

public interface NarrowMemento {
}

interface WideMemento {
  int getState();
}

class MementoImpl implements WideMemento, NarrowMemento {

  private int state;

  MementoImpl(int state) {
    this.state = state;
  }

  @Override
  public int getState() {
    return state;
  }

}

public class Originator {
  private int state;

  public Originator(final int state) {
    this.state = state;
  }

  public NarrowMemento getMemento() {
    return new MementoImpl(state);
  }

  public void setMemento(NarrowMemento memento) {
    this.state = ((WideMemento) memento).getState();
  }
}

The important bits:
  1. Originator class is public, can be used in any package. 
  2. MementoImpl class is package private thus visible only within its package.
  3. MementoWide interface is package private. 
  4. MementoNarrow marker interface is public.
Therefore only Originator and MementoNarrow are visible outside of the package and as long as Originator encapsulates its state properly it won’t leak through Memento.
This solution works fine as long as we can ensure that the Originator is used in a different package. Otherwise, the MementoWide is visible and can be used to elicit the Originator state.

There is another approach to this problem that mitigates the packaging concerns. If we want to make sure that regardless of the packaging only the Originator can access (make a call) to methods defined in the wide interface we can use method signature security. We will alter the method from the MementoWide to include a dummy class which can be constructed only by the Originator:

package memento2;

import memento2.originator.Originator;

public interface Memento {
  int getState(Originator.Stamp stamp);
}

public class MementoImpl implements Memento {

  final int state;

  public MementoImpl(final int state) {
    this.state = state;
  }

  @Override
  public int getState(Originator.Stamp stamp) {
    Objects.requireNonNull(stamp);
    return state;
  }
}

And in a different package Originator:

package memento2.originator;

import memento2.Memento;
import memento2.MementoImpl;

public class Originator {
  private final static Stamp stamp = new Stamp();

  private int state;

  public Originator(final int state) {
    this.state = state;
  }

  public Memento getMemento() {
    return new MementoImpl(state);
  }

  public void setMemento(Memento memento) {
    this.state = memento.getState(stamp);
  }

  public static class Stamp {
    private Stamp() {
    }
  }
}
The first thing that you will probably notice is that Memento interface and an implementing class are public. Still, only the Originator will be able to make a call to the exposed method. That is because its parameter is an inner class of Originator but its constructor is private so only the Originator can create a Stamp instance and make a successful call. Of course it is possible to pass a null as an argument to the method but then such client will be smacked with an NPE.
The only way this solution can be broken is by publishing an instance of the Stamp by either Memento or Originator which requires modifying a class. Therefore it is less likely to be abused than the first approach which relies only on proper packaging.

The last solution gets as close as possible to the behaviour of the Memento implemented using C++ friend class - i.e. ensuring that only the class which state we externalize can access it.

Saturday, January 28, 2012

Proxy and Adapter design patterns.

Recently, when speaking to some of my colleagues, I have noticed a lot of confusion between these two design patterns. Thus, today I'm going to clarify all the doubts :).

First off, both Proxy and Adapter belong to the same group of design patterns – structural one. What are structural design patterns? In simple words, they are patterns that describe ways of combining different entities with each other and thus forming larger structures.

And now a definition from Wikipedia:

“Structural design patterns are design patterns that ease the design by identifying a simple way to realize relationships between entities.”

Right. First we will scrutinize the adapter pattern. In a nutshell, it transforms an interface of one class into the interface that is expected. It enables two classes to work together even though their interfaces are not compatible with each other. There are two basic variations of the adapter design pattern: class adapter and object adapter.

  • Class adapter.

In this case, the adapter's class subclasses the class we want to adapt and in the same time it implements the desired interface that the client expects. When the call is made, appropriate inherited methods are being invoked.

  • Object adapter.

On the other hand, in the object adapter, the adapter's class does not subclass the adaptee but instead it holds a reference to it (composition). It also implements the expected interface.

There are pros and cons of each of these versions but in this article lets focus on more general concepts of the adapter pattern.

Now, what about the proxy pattern?

In general, it provides a surrogate of a given object in order to control the access to it in some way. Based on the way of controlling the access we can distinguish different types of proxy design pattern:

  • Remote proxy – it handles the interaction between remote objects.
  • Virtual proxy – it handles the situation when an object is expensive to create (lazy initialization).
  • Protection proxy - based on who calls the proxy, it controls the access to different methods.
  • Smart proxy – adds some extra operations when the objects is accessed.

Very important thing about the proxy pattern is the fact that the surrogate has the same interface as the real object.

To summarize. The adapter bridges the gap between two classes that are not compatible with each other. The proxy provides a surrogate to control the access to the real object.