Factory Pattern

When I ask you how to instantiate an object in Java your first answer would be:

“Creating over the new keyword and using the default or overloaded constructor.” Wouldn´t it be so?

Well of course, that one is not a bad approach or even a wrong one. It is just a bit old-fashioned and has one big handicap. When you start changing the definition of your class you want to instantiate you have to refactor every line of code in which you have instantiated the class using new and the constructor.

In a more technical view on this, you´re having a tight coupling instead of a loose coupling in your source code.
And that´s something you truly don´t want to have (Clean Code!).

Precondition Knowledge

One approach to bypass this, is the factory pattern. But before we start, take a look at the following picture, which will explain the struggle of tight and loose coupling in Java better than a thousand words could do:

As you see we have an enum which defines our different types of Smartphones. Further more we have the Smartphone class as our mother and the three children IPhone, Android and WindowsPhone.
Last but not least we have the class SmartphoneFactory which defines our buildSmartphone method for our factory.

Let´s bring it to code

Okai let´s start. First of all let us begin with the enum

package com.javadevcorner.factorypattern;

/**
 *
 * @author javadevcorner.com
 */
public enum SmartphoneType {
    IPHONE, ANDROID, WINDOWSPHONE;
}

That was simple, wasn´t it?

abstract class Smartphone

package com.javadevcorner.factorypattern;

/**
 *
* @author javadevcorner.com
*/
public abstract class Smartphone {

    private SmartphoneType model;
    
    public Smartphone(SmartphoneType smartphoneType) {
        this.model = smartphoneType;
    }
    
    public SmartphoneType getModel() {
        return model;
    }

    public void setModel(SmartphoneType model) {
        this.model = model;
    }

    protected abstract String getMyOS(); 

}

Important, watch the abstract keyword on class definition line and define the method getMyOS() as abstract, too.

Implement the different Smartphone Types

package com.javadevcorner.factorypattern;

/**
 *
 * @author javadevcorner.com
 */
public class Iphone extends Smartphone {
    
    Iphone() {
        super(SmartphoneType.IPHONE);
    }

    @Override
    protected String getMyOS() {
        return "iOS";
    }
}

Now we override our getMyOS() Method and call the super constructor in our Iphone constructor. Please move on with this, with the rest of our SmartphoneTypes

package com.javadevcorner.factorypattern;

/**
 *
 * @author javadevcorner.com
 */
public class Android extends Smartphone {

    Android() {
        super(SmartphoneType.ANDROID);
    }

    @Override
    protected String getMyOS() {
        return "Android";
    }
}
package com.javadevcorner.factorypattern;

/**
 *
 * @author javadevcorner.com
 */
public class WindowsPhone extends Smartphone {

    public WindowsPhone() {
        super(SmartphoneType.WINDOWSPHONE);
    }

    @Override
    protected String getMyOS() {
        return "Windows Phone";
    }
}

So that was the standard, and maybe know part of programming for you.

Implement our Smartphone Factory

package com.javadevcorner.factorypattern;

/**
 *
 * @author javadevcorner.com
 */
public class SmartphoneFactory {

    public static Smartphone buildSmartphone(SmartphoneType type) {
        Smartphone smartphone = null;

        switch (type) {
            case IPHONE:
                smartphone = new Iphone();
                break;
            case ANDROID:
                smartphone = new Android();
                break;
            case WINDOWSPHONE:
                smartphone = new WindowsPhone();
                break;
        }
        return smartphone;
    }
}

See what we just did here. We just control our instantiation of a Smartphone object be comparing the enum type. 

Let´s test your new findings:

package com.javadevcorner.factorypattern;

/**
 *
 * @author javadevcorner.com
 */
public class FactoryCreateMeSomeSmartphones {

    public static void main(String[] args) {
        Smartphone firstSmartphone = SmartphoneFactory.buildSmartphone(SmartphoneType.IPHONE);
        Smartphone secondSmartphone = SmartphoneFactory.buildSmartphone(SmartphoneType.ANDROID);
        Smartphone thirdSmartphone = SmartphoneFactory.buildSmartphone(SmartphoneType.WINDOWSPHONE);
        
        System.out.println(firstSmartphone.getMyOS());
        System.out.println(secondSmartphone.getMyOS());
        System.out.println(thirdSmartphone.getMyOS());
    }
    
}

Watch your output and congratulations you´ve just implemented the factory design pattern 🙂

So thanks for reading and have fun using the Factory Pattern

 

Feel free to share