M.F.M Fazrin
M.F.M Fazrin
Content Posted By
Oct 22, 2019 51 min read

Design Patterns in Java

Design-Patterns-in-Java

Design patterns in java are best practices which are used to resolve some known issues. Design patterns can be divided into 3 different types. Here we have listed down some of the widely used design patterns in Java.

  1. Singleton Design Pattern
  2. You must have heard about the Singleton Design Pattern. One of the most common question in Interviews. So here in this article, we will discuss Singleton pattern and try to resolve all queries you might have for Singleton pattern…….

  3. Factory Design Pattern
  4. In this article, I will write about the Factory Design Pattern why it is good and how to use it when writing a Java application.

  5. Decorator Design Pattern
  6. In this article, I write about the Decorator Design Pattern. This is a very nice pattern if you want to extend class behavior at runtime.

  7. Composite Design Pattern
  8. In this article, I’ll introduce the Composite Design Pattern. This pattern is used to represent part-whole hierarchies.

  9. Adapter Design Pattern
  10. In this article I’ll introduce the Adapter Design Pattern and how you can use it in Java. This pattern is mostly used to enable loosely-coupling of plugins into applications (for example the way Eclipse does this).

  11. Prototype Design Pattern
  12. This pattern is a creational pattern (just as the already introduced Factory Pattern) and it comes to play where performance matters. This pattern is used when creating a new object is costly: you use a prototype and extend it with the particular implementations of the needed object.

  13. Facade Design Pattern
  14. A facade is for hiding features from external clients and to give them a unified access point to public functionality.

  15. Proxy Design Pattern
  16. In this article, I’ll write about the Proxy Design Pattern. This pattern is used to control access to resources and objects. The real value of this pattern is to reduce memory costs for objects until you really need them.

  17. Iterator Design Pattern
  18. In this article I’ll write about the Iterator Design Pattern. This pattern is used to iterate over an aggregate object without exposing the underlying implementation of this object.

Singleton Design Pattern

What is Singleton Design Pattern?

If you are in Java then you must have used the new keyword. This new keyword creates an Object of class whenever required. But there are some scenarios where you don’t want to create individual Object for a different purpose. Singleton Pattern ensures that one and only one Object is instantiated for a given class. Whenever an object of a given class is required, only single(No more than one object) Object get returned.

Implementation of Singleton Design Pattern

Now you know what is the Singleton Design Pattern. Next step would be to implement it. There are different ways you can implement Singleton. Before you start implementation, you need to understand what are the different ways to create an Object.

Different Ways to create an Object
  • 'new' Keyword
  • Using 'the New Instance' (Reflection)
  • Cloning of an Object
  • Using Class Loader
  • Using Object De-Serialization

To make a singleton class you have to disable all these ways to create an object. One way to achieve this is to make the constructor of a given class private. But when you make the constructor private there is no way to create even a single object of the class. So first make a constructor private and then prepare a way to create an object(Single) of that class.

Implementation One

Here we will create a private Constructor and also a static method to create an object of the same class.

class JBT {

	/*
	 * This variable will be used to hold reference of JBT class.
	 */
	private static JBT instance = null;

	/*
	 * As private constructor is used so can not create object of this class
	 * directly. Except by using static method of same class.
	 */
	private JBT() {

	}

	/*
	 * This method will be used to get instance of JBT class. This method will
	 * check if there is aready an object of class create or not if not then it
	 * will create an Obect of JBT class and return the same else it will return
	 * the existing Object.
	 */
	static JBT createInstance() {
		if (instance == null){
                     instance = new JBT();
                     return instance;
              }
		else
			return instance;
	}

	int i;
}
Problem

What will happen if 2 different thread enters the createInstance method at the same time when the instance is null. In that case, threads will create 2 different objects of JBT. Which is against the Singleton pattern. In the next approach, this problem can be solved.

Implementation Two

In this approach, we will make createInstance method synchronized so only one thread is allowed in that class and only one object will be created instead of Two.

class JBT {

	/*
	 * This variable will be used to hold reference of JBT class.
	 */
	private static JBT instance = null;

	/*
	 * As private constructor is used so can not create object of this class
	 * directly. Except by using static method of same class.
	 */
	private JBT() {

	}

	/*
	 * This method will be used to get instance of JBT class. This method will
	 * check if there is aready an object of class create or not if not then it
	 * will create an Obect of JBT class and return the same else it will return
	 * the existing Object.
	 * 
	 * Now method is marked as synchronized hence only one threa will be allowed
	 * to enter in this method hence only one object will be created.
	 */
	static synchronized JBT createInstance() {
		if (instance == null){
instance = new JBT();
return instance;
}
		else
			return instance;
	}

	int i;
}
Problem

The moment we use synchronized keyword it will create a problem for our multi-threaded application in terms of performance. So on one side, we are resolving the problem on another side we are creating one more problem. In the next approach, we will solve both this problem.

Implementation Three
class JBT {

	/*
	 * This variable will be used to hold reference of JBT class.
	 * 
	 * Here we are creating the instance of JBT class and assigning the
	 * reference of that object to instance.
	 */
	private static JBT instance = new JBT();

	/*
	 * As private constructor is used so can not create object of this class
	 * directly. Except by using static method of same class.
	 */
	private JBT() {

	}

	/*
	 * This method will be used to get instance of JBT class. This method will
	 * check if there is already an object of class create or not if not then it
	 * will create an Object of JBT class and return the same else it will
	 * return the existing Object.
	 * 
	 * synchronized keyword is not required here.
	 */
	static JBT createInstance() {
		/*
		 *  As instance is already create and class loading time hence we can
		 *  directly return the same without creating any object.
		 */
		return instance;
	}

	int i;
}
Problem

Here we are creating the object of JBT when class gets loaded. The object gets created even when it is not required. The object should be created only when it is required(Lazy Loading). In the next approach, we will try to resolve this problem by using Double checking locking.

Implementation Four
package com.jbt;

public class SingletonExample {

}

class JBT {

	/*
	 * This variable will be used to hold reference of JBT class.
	 * 
	 * Here we are creating the instance of JBT class and assigning the
	 * reference of that object to instance.
	 */
	private static JBT instance = null;

	/*
	 * As private constructor is used so can not create object of this class
	 * directly. Except by using static method of same class.
	 */
	private JBT() {

	}

	/*
	 * This method will be used to get instance of JBT class. This method will
	 * check if there is already an object of class create or not if not then it
	 * will create an Object of JBT class and return the same else it will return
	 * the existing Object.
	 * 
	 * Now block is marked as synchronized instead of whole method. So synchronized
	 * part will be used only once and that is when object is null. 
	 */
	static JBT createInstance() {
		if (instance == null)
		{
			synchronized(JBT.class){
				if (instance == null){
                                   instance = new JBT();
                                   return instance;
                             }
			}
		}

			return instance;
	}

	int i;
}
Problem

All problem has been solved in this approach still synchronized keyword is used(Once) and that should be avoided.

Implementation Five (Initialization on Demand)
class JBT {

	/*
	 * As private constructor is used so can not create object of this class
	 * directly. Except by using static method of same class.
	 */
	private JBT() {

	}

	/*
	 * Here static inner class is used instead of Static variable. It means
	 * Object will be lazy initialized.
	 */
	private static class LazyInit {
		private static final JBT instance = new JBT();
	}

	/*
	 * Whenever object JBT is required this method will be invoked and it will
	 * return the instance of JBT.
	 */
	static JBT createInstance() {
		return LazyInit.instance;
	}

	int i;
}
Problem

What about Object creation using Clone and Serialization?? Next approach will handle that problem.

Implementation Six

To stop cloning of Object we will implement the Cloneable interface and throw CloneNotSupportedException. Also Serialized interface will be implemented and readObject will be used to return only one object at all time.

class JBT implements Cloneable, Serializable{

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return new CloneNotSupportedException();
	}

	protected Object readResolve() {
		return createInstance();
		}

	/*
	 * As private constructor is used so can not create object of this class
	 * directly. Except by using static method of same class.
	 */
	 private  JBT() {

	}

	/*
	 * Here static inner class is used instead of Static variable. It means
	 * Object will be lazy initialized.
	 */
	private static class LazyInit {
		private static final JBT instance = new JBT();
	}

	/*
	 * Whenever object JBT is required this method will be invoked and it will
	 * return the instance of JBT.
	 */
	static JBT createInstance() {
		return LazyInit.instance;
	}

	int i;
}

So this is the final implementation for singleton class. One more approach is there(ENUM). That I will discuss later.

Back to top

Factory Design Pattern

Why should I care?

Perhaps you have heard about programming to interfaces or just not to program to implementations. Every time you use the new keyword you create a concrete implementation of the given interface/abstract class/class. And this is bad.

Why is this bad? You may ask. There is no problem with it theoretically, using new is the “only” way you can create a new object. At least until you find another way — but for now let’s stick with new. The only opponent of new is out a well-known friend in the IT: change.

If we live the best practice of coding to interfaces we can make our application work with future implementations of this interface. As a basic example let’s write a simple method:

public void getFirst(List<String> input) {
   if(input != null && !input.isEmpty())
       return input.get(0);
   return null;
}

Here we accept a List of String objects — the implementation does not matter. And List is an interface. We could naturally use ArrayList as expected parameter but this would limit some calls to our method. For example, someone has a LinkedList (which is a different implementation of List) and in this case, he/she has to convert all the elements into an ArrayList to call our method — so using List makes it more usable for others.

What is this design pattern for?

From the basic book of Design Patters (written by the so Called Gang of Four or GoF): “Defines an interface for creating an object, but lets subclasses decide which class to instantiate.”

I would extend it with the following: a factory enables deferring the instantiation of subclasses.

Starting with…

Let’s prepare our basic example where we can start.

We have a company which creates iOS applications. Our workflow looks like this:

package hu.japy.dev.patterns;

/**
* This class contains the AppStore where we "create" iOS apps.
*
* @author Fazrin
*
*/
public class AppStore {
   public void orderApp() {

       final App app = new App();

       app.develop();
       app.test();
       app.debug();
       app.deliver();
   }
}

Currently there is only one type of application we are creating, however what about the other Apple devices (iPhone / iPad, Apple Watch and Apple TV) we could create applications for?

We can add an enum to our orderApp method to distinguish between the different target machines:

package hu.japy.dev.patterns;

/**
* Describes the available app types for our store.
*
* @author Fazrin
*
*/
public enum AppType {
   IOS,
   WATCH,
   TV
}

In this case we need different implementations of the App class because every app has its own development / testing process. In this case we can either make the App class abstract or change it to an interface. I will use the abstract solution. As you know, the difference between the two approaches is that abstract classes can have default method-implementations which children can override (as with Java 8 interfaces can have one default method but they are limited to some point).

public void orderApp(AppType type) {

   App app;
   switch (type) {
   case IOS:
       app = new IOSApp();
       break;
   case TV:
       app = new TVApp();
       break;
   case WATCH:
       app = new WatchApp();
       break;
   default:
       app = new IOSApp();
       break;
   }

   app.develop();
   app.test();
   app.debug();
   app.deliver();
}

This is fine until the already mentioned foe (change) comes along. For example Apple develops new gears and we want to stay in market so we create apps for them too, and some other products of Apple vanish with time. In this case we have to change our orderApp method again:

public void orderApp(AppType type) {

   App app;
   switch (type) {
   case IOS:
       app = new IOSApp();
       break;
   case TV:
       app = new TVApp();
       break;
   case GLASS:
       app = new GlassApp();
       break;
   default:
       app = new GlassApp();
       break;
   }

   app.develop();
   app.test();
   app.debug();
   app.deliver();
}

As you can see, instantiating concrete implementations with new can really mess up our code — and you have to change this switch block is a new app type is provided and you have to know which class to instantiate.

Factory Pattern to the rescue!

However there is the Factory Pattern we can utilize and clean up this mess:

package hu.japy.dev.patterns;

/**
* A simple Factory which encapsulates (hides) which concrete implementation to use for a given AppType.
*
* @author Fazrin
*
*/
public class AppFactory {
   public App createApp(AppType type) {
       App app;
       switch (type) {
       case IOS:
           app = new IOSApp();
           break;
       case TV:
           app = new TVApp();
           break;
       case GLASS:
           app = new GlassApp();
           break;
       default:
           app = new GlassApp();
           break;
       }
       return app;
   }
}

This is basically to move the bunch of code of decision making into a separate class ending with Factory. It seems like some lazy thing but it is the real separation of concerns. You do not want to do how to instantiate an app of a given type — you only care to process the workflow. And this factory class comes to help.

Now we can re-write the orderApp method like this:

public void orderApp(AppType type) {
   final App app = new AppFactory().createApp(type);
   app.develop();
   app.test();
   app.debug();
   app.deliver();
}

The given code is much clearer. In this case you only need to know that “There is an AppFactory which knows how to create apps of given types. Let’s get and use it!”.

From now on you do not need to know what implementation of the App interface you need to create for a given type. It is all decided by the AppFactory class. It can happen, that two types result in the same application — but you do not have to do this and you can concentrate on the order to process.

Static factories

Sometimes you can see factory classes which are static. This makes things easier because you do not need to instantiate a new version of the factory.

We could re-write our example factory above like this:

public static App createApp(AppType type) {
   App app;
   switch (type) {
   case IOS:
       app = new IOSApp();
       break;
   case TV:
      app = new TVApp();
       break;
   case GLASS:
       app = new GlassApp();
       break;
   default:
       app = new GlassApp();
       break;
   }
   return app;
}

Well, this is only a small change, adding a static modifier to the createApp method.

And then we can use it in the client like this:

public void orderApp(AppType type) {

   final App app = AppFactory.createApp(type);

   app.develop();
   app.test();
   app.debug();
   app.deliver();
}

Beside this Java instantiates this Factory class only once when your application starts so you can use some functionality all along the application — for example a unique number generation — but this is out of the scope of this article.

Conclusion

Using the Factory Design Pattern fulfills the Separation of Concerns principle, leverages your knowledge of how to get the right version for a given interface or abstract class and as a side-effect, it makes your code clearer.

However as with any of the Design Patterns do not start right away to use it in any case: make sure you can utilize all the functionality of the Design Pattern. If not it can make your code more complex and less readable!

Back to top

Decorator design pattern in Java

About the Decorator Design pattern

The concept of the decorator pattern is that it adds additional attributes to objects dynamically. This way you do not need to subclass the base to add extra functionality. This is good because with subclassing (extending) you change the behavior of all instances of the given class however you may only want some objects (instances of a given class) to change their behavior.

The Gang of Four (GoF) book states the following about this pattern:

Allows for the dynamic wrapping of objects in order to modify their existing responsibilities and behaviors.

When to use the pattern?

Knowing a pattern is good but as I mentioned earlier: use it with responsibility. Consider the following prior decorating everything in your Java project:

  • Should concrete implementations be decoupled from behaviors and responsibilities?
  • Should object responsibilities and behaviors be dynamically modifiable?

If you answer “Yes!” to the questions it may be a good idea to have subclasses but too many subclasses and too deep object-hierarchies are bad practice so you should avoid this.

How to use Decorator pattern?

First of all you need a common denominator for your objects which you can extract to an interface. This gives the contract to all of the users that the implementations have a defined set of methods which can be called.

Then you can create concrete implementors of this interface which are just normal citizens of your Java world.

And you can create a decorator which implements this interface too and has an attribute of the same interface — the object which will be decorated with this behavior. And this decorator implementation (which can be an abstract class to extend its behavior of course) implements the contract-method of the interface and implements some extra behavior to the default implementation of the attribute’s.

Seems complex? I bet with an example it will be very easy to understand.

Example

First of all let’s create the interface which gives us the contract:

/**
 * Interface to create an app
 *
 * @author Fazrin
 *
 */
public interface App {

/**
 * This method creates an app for our app store. Seems silly and broken by design to have the App develop itself but
 * for this example it fits the purpose.
 */
void developApp();

}

Now add a simple implementation of this interface which implements the contract method:

/** * @author Fazrin * */ public class IOSApp implements App {

@Override
public void developApp() {
    System.out.println("Developing an iOS app");
}

}

We are all set and have an interface with an implementation so let’s try how it works:

/**
 * This is the main entry point of the application
 *
 * @author Fazrin
 *
 */
public class AppStore {

public static void main(String... args) {
    final App app = new IOSApp();
    app.developApp();
}

}

Running this application yields the following result:

Developing an iOS app

This is quite straightforward so let’s take the next step.

We introduce the decorator. We make it for now abstract:

/**
 * This is the basic implementation for our decorator. It is abstract so it does not need to implement the contract
 * method “developApp()”.
 *
 * However it has the delegate which will be decorated later.
 *
 * @author Fazrin
 *
 */
public abstract class AppDecorator implements App {
    /**
     * This is the delegate to decorate. It is package-private so the subclasses can access it so we do not need
     * getters/setters and a constructor. However I would add one if I would write this decorator in my daily job.
     */
    App delegate;
}

And create two subclasses of this abstract Decorator to have interchangeable behavior:

/**
 * This creates a decorated App with TV extension.
 *
 * @author Fazrin
 *
 */
public class TVAppDecorator extends AppDecorator {

/**
 * A required constructor to set the delegate for this app.
 *
 * @param delegate
 *            the delegate which should be decorated.
 */
public TVAppDecorator(App delegate) {
    this.delegate = delegate;
}

@Override
public void developApp() {
    this.delegate.developApp();
    System.out.println("Adding TV extension...");
}

}

/** * This implementation of the decorator adds a Watch extension to the provided app. * * @author Fazrin * */ public class WatchAppDecorator extends AppDecorator {

/**
 * A required constructor to set the delegate for this app.
 *
 * @param delegate
 *            the delegate which should be decorated.
 */
public WatchAppDecorator(App delegate) {
    this.delegate = delegate;
}

@Override
public void developApp() {
    this.delegate.developApp();
    System.out.println("Adding Watch extension...");
}

}

As you can see, the implementations of the decorator both implement the contract method a way different so let’s see what the application’s output is if we use these decorators:

/**
 * This is the main entry point of the application
 *
 * @author Fazrin
 *
 */
public class AppStore {

public static void main(String... args) {
    final App tvApp = new TVAppDecorator(new IOSApp());
    tvApp.developApp();

    System.out.println("------");

    final App watchApp = new WatchAppDecorator(new IOSApp());
    watchApp.developApp();
}

}

Developing an iOS app
Adding TV extension…
——
Developing an iOS app
Adding Watch extension…

Naturally as I mentioned previously the decorator does not need to be an abstract class it can be a normal class too:

/**
 * This is the decorator implementation which implements the decorator pattern by itself.
 *
 * @author Fazrin
 *
 */
public class SimpleDecorator implements App {

private final App delegate;

/**
 * A required constructor to set the delegate for this app.
 *
 * @param delegate
 *            the delegate which should be decorated.
 */
public SimpleDecorator(App delegate) {
    this.delegate = delegate;
}

@Override
public void developApp() {
    System.out.println("Preparing extra content...");
    this.delegate.developApp();
    System.out.println("Fine-tuning the app to be more perfect...");
}

}

Now let’s see how this Decorator is used:

/**
 * This is the main entry point of the application
 *
 * @author Fazrin
 *
 */
public class AppStore {

public static void main(String... args) {
    final App perfectApp = new SimpleDecorator(new IOSApp());
    perfectApp.developApp();
}

}

In this case the output would be the following:

Preparing extra content…
Developing an iOS app
Fine-tuning the app to be more perfect…

Conclusion

The Decorator Pattern is very useful in some cases but it has its downsides too. For example the Decorator and its enclosed components are not identical, this means that the instanceof comparison will fail in this particular case. So keep an eye open when you use this pattern!

Back to top

Composite design pattern

Let’s see what the Gang of Four (GoF) tells us about this pattern:

“Compose objects into tree structure to represent part-whole hierarchies. Composite lets client treat individual objects and compositions of objects uniformly.”

In this pattern the client uses the component interface to interact with objects which are part of the composition. You can imagine the composite hierarchy as a tree where there are leaves and composites, and the requests are sent through this tree.

If the recipient of the call is a leaf then the request is handled directly in this leaf. If the recipient is a composite then this composite forwards the requests to its children, alternatively this composite can perform additional operations before and after forwarding.

Example

One good example for this pattern can be a company structure. For example the first entry point is the VP of Marketing who wants a new feature / software developed. So he (or she) calls up the VP of Software Development to implement this feature. The VP calls up the managers to give him a time/cost estimate. These managers forward this request to their managers or developers. When the responses get back they are returned until the VP of Software Development who answers the VP of Marketing.

Let’s define the common interface of Employee. This interface defines the methods each employee of the company has to implement.

/**
 * Interface to have a hierarchy of Employees.
 *
 * @author Fazrin
 *
 */
public interface Employee {

    /**
     * @return the name of the employee
     */
    String getName();

    /**
     * @param e
     *            add this employee to the list of employees
     */
    void add(Employee e);

    /**
     * @param e
     *            remove this employee from the list of employees
     */
    void remove(Employee e);

    /**
     * @return the list of employees
     */
    List<Employee> getEmployees();

    /**
     * This method estimates the costs in ManDays for the given project. Managers delegate this request to their
     * employees, developers return an estimate.
     *
     * @param projectDescription
     * @return
     */
    int estimateProject(String projectDescription);
}

After this I created the hierarchy structure of the company: VP, SeniorManager. TeamLeader and Developer, where developers are the leaf nodes. To use more of the DRY (Don’t Repeat Yourself) principle I introduced a common Manager class which is abstract.

/**
 * This abstract class implements the commmon functionality along all managers and gives them default methods which
 * "lazy" implementations do not have to cover.
 *
 * @author Fazrin
 *
 */
public abstract class Manager implements Employee {
    List<Employee> employees = new ArrayList<>();
    String name;

    public Manager(String name) {
        this.name = name;
    }

    @Override
    public List<Employee> getEmployees() {
        return this.employees;
    }

    @Override
    public void add(Employee e) {
        if (e != null) {
            this.employees.add(e);
        }
    }

    @Override
    public void remove(Employee e) {
        if (e != null) {
            this.employees.remove(e);
        }
    }

    @Override
    public int estimateProject(String projectDescription) {
        if (this.employees.isEmpty()) {
            return 0;
        }
        return Math.round(this.employees.stream().mapToInt(e -> {
            System.out.println(e);
            return e.estimateProject(projectDescription);
        }).sum() / this.employees.size());
    }

    @Override
    public String getName() {
        return this.name;
    }
}

/**
 * Simple implementation of a VP
 *
 * @author Fazrin
 *
 */
public class VP extends Manager {

    public VP(String name) {
        super(name);
    }

    @Override
    public String toString() {
        return "I am " + getName() + ", VP";
    }

    /**
     * VP doubles the estimated amount.
     */
    @Override
    public int estimateProject(String projectDescription) {
        System.out.println("I am " + getName() + ", the VP, and calling for an estimate...");
        final int projectEstimate = super.estimateProject(projectDescription);
        System.out.println("Original estimate: " + projectEstimate);
        return Math.toIntExact(Math.round(projectEstimate * 2));
    }
}

/**
 * Simple implementation of a Senior Manager
 *
 * @author Fazrin
 *
 */
public class SeniorManager extends Manager {

    public SeniorManager(String name) {
        super(name);
    }

    /**
     * Senior Managers add 10% to the estimate of the team.
     */
    @Override
    public int estimateProject(String projectDescription) {
        return Math.toIntExact(Math.round(super.estimateProject(projectDescription) * 1.1));
    }

    @Override
    public String toString() {
        return "I am " + getName() + ", Senior Manager";
    }
}

/**
 * Simple implementation of a Team Leader
 *
 * @author Fazrin
 *
 */
public class TeamLeader extends Manager {

    public TeamLeader(String name) {
        super(name);
    }

    @Override
    public String toString() {
        return "I am " + getName() + ", Team Leader";
    }
}

As you can see, the Senior Managers and VPs implement their own version of the estimateProject method where they multiply the already estimated time by some factor. Team Leaders trust they developers.

The Developer class has to implement some not relevant methods because they are Employees too. However because they are no managers they do not have employees so they cannot add or remove employees from their list — but they have to implement the estimateProject because developers are the leaves of this hierarchy.

/**
 * Implementation of a plain-old Developer.
 *
 * @author Fazrin
 *
 */
public class Developer implements Employee {

    String name;

    public Developer(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void add(Employee e) {
    }

    @Override
    public void remove(Employee e) {
    }

    @Override
    public List<Employee> getEmployees() {
        return null;
    }

    @Override
    public int estimateProject(String projectDescription) {
        return new Random().nextInt(24);
    }

    @Override
    public String toString() {
        return "I am " + getName() + ", Developer";
    }
}

Now let's implement a structure and see how the pattern works:

/**
 * This is the main entry point of the application.
 *
 * @author Fazrin
 *
 */
public class Composite {
    public static void main(String... args) {
        final Developer d1 = new Developer("Jack");
        final Developer d2 = new Developer("Jill");
        final Developer d3 = new Developer("Brian");
        final Developer d4 = new Developer("Bob");

        final Manager m1 = new TeamLeader("Marc");
        final Manager m2 = new TeamLeader("Christian");
        final Manager m3 = new TeamLeader("Phil");
        m1.add(d3);
        m1.add(d2);
        m2.add(d1);
        m3.add(d4);

        final Manager m4 = new SeniorManager("Harald");
        final Manager m5 = new SeniorManager("Klaus");

        m4.add(m3);
        m4.add(m2);
        m5.add(m1);

        final VP vp = new VP("Joseph");
        vp.add(m4);
        vp.add(m5);

        System.out.println("Our estimate is: " + vp.estimateProject("New exotic feature"));
    }
}

As you can see, this example requires Java 8 at least because it utilizes the new Stream API and lambdas. And here is the result of a particular run:

I am Joseph, the VP, and calling for an estimate…
I am Harald, Senior Manager
I am Phil, Team Leader
I am Bob, Developer
I am Christian, Team Leader
I am Jack, Developer
I am Klaus, Senior Manager
I am Marc, Team Leader
I am Brian, Developer
I am Jill, Developer
Original estimate: 9
Our estimate is: 18

This example output shows the tree structure where it starts with the VP and goes down for each node in the hierarchy. I could do some more fancy printing but I think you get the idea how this pattern works.

Disadvantages?

When the tree-structure is defined the composite architecture makes the tree-structure general and this makes the leaf objects to have empty methods (or which just simply return nothing valuable) like the Developer class in the example.

Conclusion

This pattern can be used in situations when the problems represent a hierarchical relationship but they tend to have empty methods for leaf nodes in this hierarchy because of a common interface.

Back to top

Adapter design pattern in java

About the pattern

Let’s see what the Gang of Four (or GoF) tell us about this pattern:

“Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.”

So as you can see the adapter pattern comes handy if you want to adapt functionality to work between incompatible types.

In this case the adapter has to be a “man in the middle” which converts the request of the source to the request accepted by the target. Naturally you can have bidirectional communication too, in this case the adapter converts the result from the target service to the one which is accepted by the source.

Downsides?

Yes, there are downsides too. Using this pattern gives more complexity to your code which makes errors harder to debug. This is why some say that this pattern is just a fix for a badly designed system — but if we take a step back and look at our system landscape we have the right to use this pattern to communicate with unchangeable legacy systems.

How to use the pattern?

To use the pattern we have to do some coding where we adapt code-base to work with another code-base.

If you have the two sides of the communication identify what your source sends and what the target accepts. If you identified this you can create the adapter in the middle which accepts the source’s call and maps it to the target’s expectation.

Example

Imagine we have a very important customer who has two systems which generate and work on data respectfully and this customer wants us to create an app which gathers data from one system and sends it to the other. We only know the interfaces which we can use — so we have to adapt the result of the first system to be a valid input of the second.

As I mentioned: the Adapter Pattern comes to rescue. The example I provide connects two libraries and converts the information between these two to fit the output into the input.

Adapting to libraries

In this first example we only have the interfaces which are the contracts of both systems:

This is the data-source system’s interface:

/**
 * This is the data provider contract. We call this to gather our data and trigger the second library to work.
 *
 * @author Fazrin
 *
 */
public interface DataProvider {
    /**
     * Gets some data which is provided by the system somehow.
     *
     * @return a DTO containing the resulting information – can be null.
     */
    public FirstSystemDTO getData();
}

This is the DTO which is returned

/** * The DTO to transfer the results of some data gathering to the callers. * * @author Fazrin * */ public abstract class FirstSystemDTO { /** * @return the first name value – can be null */ public abstract String getFirstName();

/**
 * @return the middle name value -- can be null
 */
public abstract String getMiddleName();

/**
 * @return the last name value -- can be null
 */
public abstract String getLastName();

}

And here is the information consumer:

/** * This is the second system’s contract which we want to call after the data is gathered from the first system. * * @author Fazrin * */ public interface DataConsumer { /** * Triggers some work based on the parameter in the system. * * @param name * the work is based on this parameter * * @throws NullPointerException * if name is null */ void triggerWorker(String name); }

As you can see, this second system does not know what to do with a FirstSystemDTO and this DTO does not have a convenience method which returns the whole name. So a method call like the following is out of the question:

dataConsumerInstance.triggerWork(dataProviderInstance.getData());

This would be too nice. Beside this the first system is very lazy, it can return null everywhere which is not too good. Anyway we create the application and we need a solution to map between the two systems. So our code has to be the adapter:

public class Adapter {

DataProvider dataProviderInstance = new DataProviderInstance();
DataConsumer dataConsumerInstance = new DataConsumerInstance();

/**
 * This method is the adapter which gets the data from the provider and triggers the consumer.
 */
public void doOurWork() {
    final FirstSystemDTO data = this.dataProviderInstance.getData();
    this.dataConsumerInstance.triggerWorker(dataToString(data));
}

/*
 * This method converts the gathered information into a null-safe String
 */
private String dataToString(FirstSystemDTO data) {
    if (data == null) {
        return "";
    }
    return join(" ", data.getFirstName(), data.getMiddleName(), data.getLastName());
}

}

As you can see it is not very hard to create an adapter for two libraries, the only thing you need is some code to write. Naturally this example was very trivial and sometimes you need to write more code to map requirements between two interfaces.

The join function concatenates a list of strings with a given string delimiter. The first parameter is the delimiter, the others are varargs for the strings to concatenate.

Adapting to services

Adapting to external services is almost the same than adapting to interfaces. Sometimes you have transfer objects (DTOs) to accept and send, sometimes you need to call the services directly with some parameters.

A good use-case for this would be a web-service where you have an external system which provides a DTO to communicate with but you need to convert this DTO into a format which you can accept.

Conclusion

The Adapter pattern is useful to solve communication / protocol problems between systems. So use this pattern only if the system is designed and in production or you have a third-party solution where you cannot change the codebase to be right. While you are developing software look at the Bridge pattern.

What is the Prototype design pattern about?

This pattern is a creational pattern (just as the already introduced Factory Pattern) and it comes to play where performance matters. This pattern is used when creating a new object is costly: you use a prototype and extend it with the particular implementations of the needed object.

The best use-case for this pattern if an object is created after a costly database operation: you get all the data with the query (or queries) and you can use this information later to have new objects populated. With this approach you can reduce the number of database operations and save some I/O time for your application.

And to have one word in comparison with the introduced Factory Patter: the Factory Pattern is creation through inheritance, the Prototype Pattern is creation through delegation.

How to apply the pattern?

Well, if you use Java since some time and apply the Object-Oriented patterns you already know this pattern: it comes with abstraction and polymorphism.

OK, actually this is only the base of the pattern, you need some more things to do. Here I’ll will give you an insight on my best practices how to apply this pattern.

Have a clone method

For this define a base class (I suggest it to be abstract but this may vary depending on your needs) and it should implement the java.lang.Cloneable interface — which only indicates that the Object.clone() method is a valid operation on this type of object (this means that the Cloneable interface does not have any methods defined).

/**
 * Base abstract class for the Prototype Pattern.
 *
 * @author Fazrin
 *
 */
public abstract class App implements Cloneable {

    private AppType type;

    public abstract void develop();

    public void test() {
    }

    public void debug() {
    }

    public void deliver() {
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public AppType getType() {
        return this.type;
    }

    protected void setType(AppType type) {
        this.type = type;
    }
}

After the abstract class is ready, let's create some implementations.

/**
 * @author Fazrin
 *
 */
public class IOSApp extends App {

    public IOSApp() {
        System.out.println("Creating an iOS App");
        setType(AppType.IOS);
    }

    @Override
    public void develop() {
        System.out.println("Developing an iOS App");
    }

}

/**
 * @author Fazrin
 *
 */
public class WatchApp extends App {

    public WatchApp() {
        System.out.println("Creating a watch app");
        setType(AppType.WATCH);
    }

    @Override
    public void develop() {
        System.out.println("Developing a Watch App");
    }

}

Have a cache of prototypes

Because creating an App costs time (because we load it from the database) let’s create a cache to store those Apps.

The best choice for the cache in my opinion is a java.util.HashMap because it has a very fast (constant) time value for the basic operations: put and get.

/**
 * This is the cache where we store the Apps which were loaded from the "database".
 *
 * @author Fazrin
 *
 */
public class BasicAppCache {
    Map<AppType, App> appCache = new HashMap<>();

    /**
     * Loads all available types of the application and puts them into the cache.
     */
    public void load() {
        System.out.println("Loading App of type " + AppType.IOS.name());
        this.appCache.put(AppType.IOS, new IOSApp());
        System.out.println("Loading App of type " + AppType.WATCH.name());
        this.appCache.put(AppType.WATCH, new WatchApp());
    }

    /**
     * Gets the app from the cache based on its type
     */
    public App get(AppType type) {
        System.out.println("Getting App of type " + type.name());
        final App app = this.appCache.get(type);
        if (app != null) {
            try {
                return (App) app.clone();
            } catch (final CloneNotSupportedException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

This cache cam have a load method which can initially load all the known objects from the database and add it to the cache. For such a small example this is a good approach however in real-life scenarios it should handle each request and decide on the contents of the cache if it should be loaded or just replicated from the cache.

/**
 * This is the cache where we store the Apps which were loaded from the "database".
 *
 * @author Fazrin
 *
 */
public class AdvancedAppCache {
    Map<AppType, App> appCache = new HashMap<>();

    private App load(AppType type) {
        System.out.println("Loading App of type " + type.name());
        switch (type) {
        case IOS:
            final App app = new IOSApp();
            this.appCache.put(type, app);
            return app;
        case WATCH:
            final App watchApp = new WatchApp();
            this.appCache.put(type, watchApp);
            return watchApp;
        default:
            return null;
        }

    }

    public App get(AppType type) {
        System.out.println("Getting App of type " + type.name());
        App app = this.appCache.get(type);
        // the type is not in the cache, let's load it
        if (app == null) {
            app = load(type);
        }
        try {
            // we have to cast the result of clone() to App because the default return type is Object
            return (App) app.clone();
        } catch (final CloneNotSupportedException e) {
            // a nasty exception, let's just ignore it
            e.printStackTrace();
        }
        // if everything fails, return simply null
        return null;
    }
}

As you can see, the cache determines if the object is already loaded or not and based on this information it loads and adds it to the cache or just returns a new clone from the already loaded object.

Have a factory

We already learned about the Factory Patterns which defers the instantiation of the classes. This means that you do not need to create every object you need with new and you do not need to know the concrete implementation of a given interface or abstract class you want to use.

/**
 * This factory is used to create a new Application.
 *
 * It utilizes the BasicAppCache.
 *
 * @author Fazrin
 *
 */
public class AppFactory {
    BasicAppCache appCache;

    public AppFactory() {
        this.appCache = new BasicAppCache();
        this.appCache.load();
    }

    public App createApp(AppType type) {
        return this.appCache.get(type);
    }
}

In this example the Factory calls the cache and does not want to know about how the cache deals with object creation.

Use the factory!

Now it is time to use the factory in our simple application. Here we will create some apps and display what is happening. And instead of creating ever instance with new we use the previously defined factory.

/**
 * This is the main entry point of the application.
 *
 * @author Fazrin
 *
 */
public class AppStore {

    public void orderApp(AppType type) {
        final App app = new AppFactory().createApp(type);
        app.develop();
        app.test();
        app.debug();
        app.deliver();
    }

    public static void main(String... args) {
        new AppStore().orderApp(AppType.WATCH);
    }
}

And here is an output of the previous application running:

Loading App of type IOS
Creating an iOS App
Loading App of type WATCH
Creating a watch app
Getting App of type WATCH
Developing a Watch App

We could use the cache itself instead of the factory in the example above but in this case you have to know that there is a cache behind the scenes. If you later decide that you do not need a cache and won’t use the prototype pattern anymore then you have to rework all the places where you create new apps.

However I’ll include the use case where we can use the caches directly. An alternative would be to have a CacheFactory and hide the implementations of the cache but this article is not about the Factory Pattern.

public static void main(String... args) {
    final BasicAppCache basicCache = new BasicAppCache();
    basicCache.load();
    for (final AppType t : AppType.values()) {
        basicCache.get(t);
    }
    for (final AppType t : AppType.values()) {
        basicCache.get(t);
    }

    System.out.println("------");

    final AdvancedAppCache advancedCache = new AdvancedAppCache();
    for (final AppType t : AppType.values()) {
        advancedCache.get(t);
    }
    for (final AppType t : AppType.values()) {
        advancedCache.get(t);
    }
}

As you can see we use both caches two times to see how they work and here is the output:

Loading App of type IOS
Creating an iOS App
Loading App of type WATCH
Creating a watch app
Getting App of type IOS
Getting App of type WATCH
Getting App of type IOS
Getting App of type WATCH
------
Getting App of type IOS
Loading App of type IOS
Creating an iOS App
Getting App of type WATCH
Loading App of type WATCH
Creating a watch app
Getting App of type IOS
Getting App of type WATCH

As you can see, the BasicAppCache loads (creates) the objects when the load() method is called, the AdvancedAppCache loads the entries on demand. This means if you forget to call load() on the BasicAppCache you’ll end up with no Apps.

Conclusion

As mentioned in the introduction, the Prototype Pattern is best used with creation through delegation. It can be used with the Factory Pattern (using a Factory) to hide the implementation details from the user of our service but it is not a must, you can access the class caching the prototypes too.

For an application in production I suggest to use the Advanced App Cache solution where entries are loaded on-demand. It is nicer, more performance at the beginning (giving a bit of slow performance if a prototype is not in the cache) but you can start faster and make your users happier — not to mention the call of load() when using the BasicAppCache which can lead to unexpected errors.

Back to top

About the Facade Design Pattern

A facade is for hiding features from external clients and to give them a unified access point to public functionality.

Let’s see what the Gang of Four (GoF) tells us about this pattern:

“Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.”

So to have this pattern applied in your application your goal is to isolate your client from the code of your application.

You can use this pattern in a Service Oriented Architecture (SOA): for example a service enables access to other smaller services. You do not have to think in this case that these are web services and outside clients: you can have this pattern applied to your application too as you design it and restrict access between packages (this requires some build-time validation too however tools like SonarQube are capable of this).

Another way to use this pattern is to encapsulate complex functionality from the caller of your facade: you have a complex system in the background and when using this systems you need to fire up queries, ask other services and do various calculations to get the result. If you would access it normally you would need to know each service, the order to call them to get your result. With a facade in-between you only let one method known by your users and you can configure the logic in the facade.

Example

The best example is again the AppStore where we can order an app and we do not have to know what happens in the background: the app is developed and tested. And we are happy that we don’t have to call every phase of the development life-cycle ourself just the one facade.

Let’s see how this works with a simple example. In this app store we have a 3-phase development: first a Design is created by an AppDesigner based on some requirements. Then an AppDeveloper develops an App based on the Design. When the App is ready an AppTester verifies that the App is working as defined in the Design.

First of all, let’s create the Design and App classes:

/**
 * Simple class to mock a design object for an app.
 *
 * @author Fazrin
 *
 */
public class Design {

    private final String requirements;

    public Design(final String requirements) {
        this.requirements = requirements;
        System.out.println(toString());
    }

    @Override
    public String toString() {

        return "App design for requirements: " + requirements;
    }
}

/**
 * Simple app mock which does nothing currently.
 *
 * @author Fazrin
 *
 */
public class App {

    private final String title;

    public App(final Design design, final String title) {
        System.out.println("Creating an app based on the design: " + design);
        this.title = title;
    }

    @Override
    public String toString() {

        return "Fantastic app with title: " + title;
    }
}

Then we create the back-end workers:

/**
 * Simple designer class.
 *
 * @author Fazrin
 *
 */
public class AppDesigner {

    public static Design design(final String requirements) {

        return new Design(requirements);
    }
}

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Simple app developer mock.
 *
 * @author Fazrin
 *
 */
public class AppDeveloper {

    private static final List<String> POSSIBLE_NAMES = Arrays.asList("Pointless Kangaroo",
            "Moon Forgotten", "Purple Rusty Space", "Blue Vulture", "Skilled Ostrich", "Saturday's Intense Xylophone",
            "Harsh Reborn Gravel", "Liquid Rhinestone", "Wooden Haystack", "Scissors Olive", "Moving Doorstop",
            "Strong Restless Arm", "Dreaded Pottery");

    public static App develop(final Design design) {

        Collections.shuffle(POSSIBLE_NAMES);

        return new App(design, POSSIBLE_NAMES.get(0));
    }
}

/**
 * A simple app tester.
 *
 * @author Fazrin
 *
 */
public class AppTester {

    public static boolean test(final App app, final Design design) {

        System.out.println("Testing app: " + app + ", based on the design " + design);

        return Math.random() < 0.5;
    }
}

Without a facade we have to know how every component works until we have our final App. An example of calling the workers is listed here:

/**
 * Entry point for the application and here we can order our apps.
 *
 * @author Fazrin
 *
 */
public class AppStore {

    public static void main(final String... args) {

        Design d = AppDesigner.design(
                "Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.");

        App app = AppDeveloper.develop(d);
        while (!AppTester.test(app, d)) {
            System.out.println("App " + app + " failed the tests :(");
        }
    }
}

And an example output:

App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.
Creating an app based on the design: App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.
Testing app: Fantastic app with title: Pointless Kangaroo, based on the design App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.
App Fantastic app with title: Pointless Kangaroo failed the tests 🙁
Testing app: Fantastic app with title: Pointless Kangaroo, based on the design App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.
App Fantastic app with title: Pointless Kangaroo failed the tests 🙁
Testing app: Fantastic app with title: Pointless Kangaroo, based on the design App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.
App Fantastic app with title: Pointless Kangaroo failed the tests 🙁
Testing app: Fantastic app with title: Pointless Kangaroo, based on the design App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.

To leverage our AppStore from the knowledge of who has to work on the App (perhaps we want to introduce some other step in the creation process like UX testers) we encapsulate the functionality into a facade:

/**
 * This is the facade where the apps are created.
 *
 * @author Fazrin
 *
 */
public class AppCreationFacade {

    public static App orderApp(final String requirements) {

        Design d = AppDesigner.design(requirements);
        App app = AppDeveloper.develop(d);
        while (!AppTester.test(app, d)) {
            System.out.println("App " + app + " failed the tests :(");
        }

        System.out.println("Successfully developed " + app);

        return app;
    }
}

As you can see, this facade does basically the same thing as we did previously in the AppStore. However with this approach we hide the implementation details from the clients of the facade and only the facade has to know how it gets an App from the initial requirements.

From the AppStore we only have to call the right method of the facade:

/**
 * Entry point for the application and here we can order our apps.
 *
 * @author Fazrin
 *
 */
public class AppStore {

    public static void main(final String... args) {
        AppCreationFacade.orderApp(
                "Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.");
    }
}

Here is an example output of the above example application:

App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.
Creating an app based on the design: App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.
Testing app: Fantastic app with title: Saturday’s Intense Xylophone, based on the design App design for requirements: Create me a cool app which knows everything I want and makes this fast. And of course it has to be cheap.
Successfully developed Fantastic app with title: Saturday’s Intense Xylophone

Conclusion

As you could see, using this design pattern is nothing tricky — and if you work with Java applications then you may already used this pattern without noticing it.

Back to top

About the Proxy Design pattern

Let’s see what the Gang of Four (GoF) says about this pattern:

“Allows for object level access control by acting as a pass through entity or a placeholder object.”

So this makes sense and as in the introduction already mentioned: it has a very good use to reduce resource cost. For example you load something from your database, a huge object, and don’t want to initialize all its properties at once only on demand. In this case you create a proxy object which is later “de-proxied” when needed. With this approach you save some performance. If you are familiar with JPA and/or Hibernate you may know that this is an approach persistence provider use to save some memory when doing lazy fetching.

In practice the client gets the proxy object when calling for something. If the client needs details it calls the right methods on the proxy object which then delegates to the target.

Example

Today’s example is a very simple one. We will create a simple library where we want to load objects containing a big text from the database (BLOB or CLOB for relational database users) or the file system. This is interesting because it can consume memory to have these large texts in memory — and to load them from an external source too.

The easiest way to support compatibility between the proxy and the real target is to have a common interface between them which enables the client to know which methods it can use and to hide that it has a proxy instead of a real object.

We create an interface for the object, let’s call it Book:

/**
 * The common interface between the Proxy and the Real object.
 *
 * @author Fazrin
 *
 */
public interface Book {

    String getTitle();

    String getAuthor();

    String getContent();
}

Now we need our real implementation of the book. This implementation takes care of loading the big data at construction time.

import java.text.MessageFormat;

/**
 * A simple implementation of our real book which loads its contents when constructed.
 *
 * @author Fazrin
 *
 */
public class RealBook implements Book {

    private final String title;
    private final String author;
    private String content;

    public RealBook(final String title, final String author) {
        this.title = title;
        this.author = author;
        loadContentFromDatabase(title, author);
    }

    @Override
    public String getTitle() {

        return title;
    }

    @Override
    public String getAuthor() {

        return author;
    }

    @Override
    public String getContent() {

        return content;
    }

    private void loadContentFromDatabase(final String title, final String author) {

        System.out.println("Loading content from database...");
        try {
            Thread.sleep(2500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.content = MessageFormat.format("Interesting and very large content of {0} by {1}", title, author);
    }
}

The sleep in the loadContent method is for simulate the time elapsed when loading the example.

To avoid loading every time we create a proxy object: this has almost the same information than the real book but the proxy only loads the content on-demand.

/**
 * Simple proxy implementation which only loads the content when it is needed. Until that it handles the available
 * information as it were the real book.
 *
 * @author Fazrin
 *
 */
public class ProxyBook implements Book {

    private final String title;
    private final String author;
    private RealBook realBook;

    public ProxyBook(final String title, final String author) {
        this.title = title;
        this.author = author;
    }

    @Override
    public String getTitle() {

        return title;
    }

    @Override
    public String getAuthor() {

        return author;
    }

    @Override
    public String getContent() {

        if (realBook == null) {
            realBook = new RealBook(title, author);
        }
        return realBook.getContent();
    }
}

And finally let’s create a LibraryService where you can look-up books by title and author.

import static java.util.stream.Collectors.toMap;

import java.util.Map;
import java.util.stream.Stream;

/**
 * Simple service to find the right books and load their content.
 *
 * And this is the main entry point of the application too.
 *
 * @author Fazrin
 *
 */
public class LibraryService {

    public static void main(final String... args) {

        new LibraryService().findContentByAuthorAndTitle("GoF", "Design Patterns").entrySet()
                .forEach(b -> System.out.println(b.getKey() + " --> " + b.getValue()));
    }

    /**
     * Finds the right book for our test purposes and then loads its content.
     */
    public Map<String, String> findContentByAuthorAndTitle(final String author, final String title) {

        return filterByTitle(filterByAuthor(findAllBooks(), author), title)
                .collect(toMap(Book::getTitle, Book::getContent));
    }

    /*
     * The following methods are really simple and I think straightforward too.
     */
    private Stream<Book> findAllBooks() {

        return Stream.of(new ProxyBook("Design Patterns", "Gabor Laszlo Hajba"),
                new ProxyBook("Design Patterns", "GoF"), new ProxyBook("Python 3 in Anger", "Gabor Laszlo Hajba"),
                new ProxyBook("Design Patterns", "Head First"));
    }

    private Stream<Book> filterByAuthor(final Stream<Book> books, final String author) {

        return books.filter(b -> author.equals(b.getAuthor()));
    }

    private Stream<Book> filterByTitle(final Stream<Book> books, final String title) {

        return books.filter(b -> title.equals(b.getTitle()));
    }
}

Running the result we get the following written to the console:

Loading content from database…
Design Patterns –> Interesting and very large content of Design Patterns by GoF

As you can see in the example above, loading the whole book contents happens only when it is needed. If we aren’t interested in a given book it’s content is not loaded.

Conclusion

The Proxy Design Pattern is very useful to leverage loading and memory overhead until that moment where you really need the cause of the overhead.

Back to top

Iterator Design Pattern

As I mentioned, this pattern is used to iterate over an object which holds a collection of other objects — and you hide the implementation of the iteration from the user who calls the iterator. For a Java example: you can iterate with a for loop the same way through a java.util.List (regardless of the implementation) or a java.util.Set. And for List implementations it does not matter if you have an ArrayList or a LinkedList.

The problem

The problem which is solved with the iterator pattern is the one to create an abstraction above these collection objects to enable different kinds of iteration — without writing the whole set of methods into the interface (for example of java.util.List). Because Java knows generics you may need to support multiple types of objects in your collection — and for this you’d need several methods which would blow-up your interface.

If you want to support three data structures (arrays, lists and maps) and three operations for each collection (sort, merge and find) you would need 3×3 classes to support this functionality (i.e. ArraySorter, ArrayMerger, ArrayFinder, etc.) — which you have to maintain later on.

Although nine classes do not seem very tragical but this is only an example. The generic result would be n x m classes where n is the amount of data structures and m is the amount of algorithms. For 5 different data structures and 8 algorithms you need 40 different classes to maintain. This is bad, isn’t it?

The solution

The solution is to have a generic approach and have only three classes to support your collection algorithms and of course your three structure classes. For the example in the previous section these are 6 classes — which is not much reduction from the 9. However if we look at the second example from the previous section we need only 13 classes to maintain because the generic programming approach requires n + m classes to maintain.

Example

Let’s see a basic example how we can use the iterator pattern to encapsulate our objects and their iteration.

First of all here is a simple data structure which represent a set of elements:

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * This class is the data container holding information we want to iterate through.
 *
 * @author Fazrin
 *
 */
public class DataContainer {

    private final Set<String> data = new HashSet<>();

    public void add(String element) {
        this.data.add(element);
    }

    public Collection<String> getData() {
        return this.data;
    }
}

Now let’s loop over this list with an Iterator provided by the underlying data of the class:

import java.util.Collection;
import java.util.Iterator;

/**
 * This is the main entry point of the application.
 *
 * @author Fazrin
 *
 */
public class Main {
    public static void main(String... args) {
        final DataContainer dc = new DataContainer();
        dc.add("Iterator");
        dc.add("Design");
        dc.add("Pattern");
        dc.add("by");
        dc.add("Gabor");
        dc.add("Hajba");

        Collection<String> data = dc.getData();

        final Iterator<String> it = data.iterator();
        while (it.hasNext()) {
            System.out.print(it.next() + "  ");
        }
        System.out.println();

        data.clear();
        data = dc.getData();
        System.out.println("size of data is " + data.size());
    }
}

Finally let’s run this example. Your output may look a bit different as of how a Set stores the elements.

Design  Pattern  Hajba  by  Iterator  Gabor 
size of data is 0

As you can see, in the example above we have to know that the getData() method returns a Collection which already has an iterator. Beside this we can clear the collection of the DataContainer class out of classes where we access the data — which can lead to hard-to-find problems: for example we can delete the contents of the container object.

Let’s find a solution to this problem. A fair approach is to create our own iterator and restrict the access as much as we need it.

The first step could be to create an interface common to all of our container objects. However I’ll skip this because we only have one class in this simple example.

So let’s hide the information in our container and enable access to an iterator which will go through our data set:

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * This class is the data container holding information we want to iterate through.
 *
 * @author Fazrin
 *
 */
public class IterableDataContainer {

    private final Set<String> data = new HashSet<>();

    public void add(String element) {
        this.data.add(element);
    }

    public Iterator<String> getIterator() {
        return new DataIterator(this);
    }

    private Set<String> getData() {
        return this.data;
    }

    private class DataIterator implements Iterator<String> {

        private final Iterator<String> iterator;

        public DataIterator(IterableDataContainer cont) {
            this.iterator = cont.getData().iterator();
        }

        @Override
        public boolean hasNext() {
            return this.iterator.hasNext();
        }

        @Override
        public String next() {
            if (this.iterator.hasNext()) {
                return this.iterator.next();
            }
            return null;
        }
    }
}

Now it is time to modify our running script to use the new iterator instead of the old access-based version:

import java.util.Iterator;

/**
 * This is the main entry point of the application.
 *
 * @author Fazrin
 *
 */
public class Main {
    public static void main(String... args) {

        final IterableDataContainer dc = new IterableDataContainer();
        dc.add("Iterator");
        dc.add("Design");
        dc.add("Pattern");
        dc.add("by");
        dc.add("Gabor");
        dc.add("Hajba");

        final Iterator<String> it = dc.getIterator();
        while (it.hasNext()) {
            System.out.print(it.next() + "  ");
        }
        System.out.println();
    }
}

As you can see, we have no access to the data in the container (you do not know the size and cannot clear the contents). Naturally you can add methods to the IterableDataContainer class to enable access to the size or lear the underlying container — but as you can see, you are in charge and you cannot allow total disposal of elements.

Let’s run the example one more time:

Conclusion

The Iterator pattern can be used to create a common way to enable users to iterate through a collection of elements in your container.