Creational Design Patterns

CREATIONAL PATTERNS
These design patterns provide a way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects need to be created for a given use case.

SINGLETON PATTERN :

In object-oriented programming, a singleton class is a class that can have only one object (an instance of the class) at a time.

After first time, if we try to instantiate the Singleton class, the new variable also points to the first instance created. So whatever modifications we do to any variable inside the class through any instance, it affects the variable of the single instance created and is visible if we access that variable through any variable of that class type defined.

To design a singleton class:

Make constructor as private.
Write a static method that has return type object of this singleton class.

class Mother
{
    private String name;

    private static Mother m = null;

    private Mother(String n)
	{

		name = n;
	}

	public Mother getMother(String n)
	{

	        if(m==null)
				m = new Mother(n);
			return m;
	}
}

For a child class there can be only one mother instance hence Mother class is a singleton class. We keep the constructor private and make a getMother() method which will be called from outside to instantiate a new Mother object. If an object of Mother class is already created before that same instance will be returned else a new Mother object will be returned.

FACTORY DESIGN PATTERN AND ABSTRACT FACTORY :

Factory method is a creational design pattern, i.e., related to object creation. In Factory pattern, we create object without exposing the creation logic to client and the client use the same common interface to create new type of object.

Factory method creates the object and returns it to the client(one who calls the factory method) depending on the parameter passed. So if we have to insert a new object type we will add code to the factory method and not in the client. The object type is the concrete product and it’s base class is the product.

Let’s first create an interface for a product to be manufactured by the factory.


/**

 * Product interface

 */

public interface GeometricShape {

    void draw();

}

The following are the implementations of the above interface:

/**

 * Concrete Product

 */

public class Line implements GeometricShape {

    @Override

    public void draw() {

        System.out.println("Line Drawn.");

    }

}

/**

 * Concrete Product

 */

public class Rectangle implements GeometricShape {

    @Override

    public void draw() {

        System.out.println("Rectangle is drawn.");

    }

}

/**

 * Concrete product

 */

public class Circle implements GeometricShape{

    @Override

    public void draw() {

        System.out.println("Circle is drawn.");

    }

}

I have added the following enums to name the shapes:

public enum ShapeType {
    LINE,
    CIRCLE,
    RECTANGLE,
    TRIANGLE
}

Now, let’s create a factory that provides the product (in this case, GeometricShape):

/**

 * Concrete Product

 */

public abstract class ShapeFactory {

    public static GeometricShape getShape(ShapeType name) {
        GeometricShape shape = null;
        switch (name) {
            case LINE:
                shape = new Line();
                break;

            case CIRCLE:
                shape = new Circle();
                break;

            case RECTANGLE:
                shape = new Rectangle();
                break;
        }

        return shape;
    }

}

The client for the application provides the name of the shape required as follow.

/**

 * Client

 */

public class Application {
    public static void main(String[] args) {

        //requests for circle shape

        GeometricShape circle = ShapeFactory.getShape(ShapeType.CIRCLE);
        if (circle != null) {
            circle.draw();
        } else {
            System.out.println("This shape can not be drawn.");
        }

        //requests non existent shape

        GeometricShape triangle = ShapeFactory.getShape(ShapeType.TRIANGLE);
        
        if (triangle != null) {
            triangle.draw();
        } else {
            System.out.println("This shape can't be drawn");
        }

    }
}

The output of the program is:

Circle is drawn.

This shape can’t be drawn

BUILDER PATTERN

Builder pattern aims to “Separate the construction of a complex object from its representation so that the same construction process can create different representations.” It is used to construct a complex object step by step and the final step will return the object. The process of constructing an object should be generic so that it can be used to create different representations of the same object.

Below is the coded solution of problem we discussed above. This uses a additional class UserBuilder which helps us in building desired User object with all mandatory attributes and combination of optional attributes, without loosing the immutability.

public class User
{

    //All final attributes

    private final String firstName; // required
    private final String lastName; // required
    private final int age; // optional
    private final String phone; // optional
    private final String address; // optional

 

    private User(UserBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.phone = builder.phone;
        this.address = builder.address;
    }

 

    //All getter, and NO setter to provde immutability

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }

 

    @Override

    public String toString() {
        return "User: "+this.firstName+", "+this.lastName+", "+this.age+", "+this.phone+", "+this.address;
    }

 

    public static class UserBuilder
    {
        private final String firstName;
        private final String lastName;
        private int age;
        private String phone;
        private String address;
 

        public UserBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public UserBuilder address(String address) {
            this.address = address;
            return this;
        }

        //Return the finally consrcuted User object

        public User build() {
            User user =  new User(this);
            validateUserObject(user);
            return user;
        }

        private void validateUserObject(User user) {

            //Do some basic validations to check

            //if user object does not break any assumption of system

        }
    }
}

And below is the way, we will use the UserBuilder in our code:


public static void main(String[] args) {
    User user1 = new User.UserBuilder("Lokesh", "Gupta")
    .age(30)
    .phone("1234567")
    .address("Fake address 1234")
    .build();

    System.out.println(user1);

    User user2 = new User.UserBuilder("Jack", "Reacher")
    .age(40)
    .phone("5655")
    //no address
    .build();

    System.out.println(user2);

    User user3 = new User.UserBuilder("Super", "Man")
    //No age
    //No phone
    //no address
    .build();

    System.out.println(user3);
}

Output:

User: Lokesh, Gupta, 30, 1234567, Fake address 1234

User: Jack, Reacher, 40, 5655, null

User: Super, Man, 0, null, null

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Post Navigation