Factory -> Creational Arrogant Design Pattern

Arrogant Design Patterns ( by Hafiz Waleed Hussain )

Hi, I hope everyone is doing good.

Today, we are going to start our series of Arrogant Design Patterns. In our list first, we have a Factory Pattern which belongs to a Creational Design Pattern group. But for now, we don’t care. We will be a focus on the use case, where we should use Factory Pattern, and later you guys will automatically find out the group of this Design Pattern.

In case you missed the Introductory Post of Arrogant Design Patterns.
More Posts on Design Patterns https://www.uwanttolearn.com/design-patterns/

Revision:

We need to do some concepts revise, which are essential from the perspective of Design Patterns.

I am sure everyone who is reading this blog is aware of how to use

  • if, else if, switch, when
  • for loop, while loop, do-while loop
  • Functions,
  • Classes, Objects
  • Inheritance, Encapsulation, Polymorphism
  • Composition
  • Dependency Injection
  • Single Responsibility Principle
  • Open-Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation
  • Dependency Inversion Principle

Still, I am going to revise some of the concepts :).

Note: I am going to use the kotlin and java syntax, but you can relate these examples with any OOP language.

How to create an Object:

class NameOfAClass{}
val objectOfAClass = NameOfAClass()

In the above code, first I created a class with the name “NameOfAClass” and after that, I created an object from this class.

Inheritance:

open class Parent{}
class Child : Parent(){}

// In Java
public class Parent{ }
public class Child extends Parent{}

In the above code, Parent is a class and Child is also a class but that class also inherits the Parent.

Polymorphism:

I am not going to explain what is Polymorphism, for that you can ask Google. I am going to show you how we can create a Polymorphism scenario.

open class Parent{
open fun doSomething(){
println("Do Something")
}
}

class ChildOne: Parent(){
override fun doSomething(){
super.doSomething()
println("ChildOne Do Something")
}
}

class ChildTwo: Parent(){
override fun doSomething(){
super.doSomething()
println("ChildTwo Do Something")
}
}

fun main() {
var parent: Parent = ChildOne()
parent = ChildTwo()
}

// In Java

public class Parent{ 
    void doSomething(){
        System.out.println("Do Something");
    }
}
public class ChildOne extends Parent{
    void doSomething(){
        super.doSomething();
        System.out.println("ChildOne Do Something");
    }
}

public class ChildTwo extends Parent{
    void doSomething(){
        super.doSomething();
        System.out.println("ChildTwo Do Something");
    }
}

public static void main(String[] args) {
    Parent parent = new ChildOne();
    parent = new ChildTwo()
}

In the above code, we have three classes, Parent, ChildOne and ChildTwo. ChildOne and ChildTwo are both inherit from Parent class. Now, where is polymorphism? We can see Polymorphism in the main method.

public static void main(String[] args) {
    Parent parent = new ChildOne();
    parent.doSomething()
   
    parent = new ChildTwo()
    parent.doSomething()
}

Basically, in this code, everything in front of us, that is why we can see, and we can predict Polymorphism behavior like when a parent.doSomething() called the first time, we will see the output of ChildOne implementation and when the second time parent.doSomething() called we would see the ChildTwo implementation. So the Parent is showing us a Polymorphic behavior. You need to remember this, instead, here I can see a Factory Pattern use case, but for now, if you are not able to see a Factory Pattern use case, it’s Okay. You will see one-day :).

Before going to the next revision topic. I am going to change something in the above main method code so we can see a unpredict Polymorphism behavior.

public static void main(String[] args) {
    Parent parent = getInstanceOfChild();
    parent.doSomething()
}

Now, anyone can tell me what will be the output of parent.doSomething() with your current knowledge? I know, No one can give me the answer until we see the implementation of getInstanceOfChild(). We can say, parent is still showing a Polymorphism, but from the perspective of the main method, I introduce an abstraction. Like you only know the interface of the getInstanceOfChild(), but you are not aware of the implementation of getInstanceOfChild(). 

Composition:

Again, I am not going to explain what is Composition you can consult from Google. Instead, I am going to show you how to achieve Composition in our above inheritance example.

class Parent{
    open fun doSomething(){
        println("Do Something")
    }
}

class ChildOne(val parent: Parent){
    fun doSomething(){
        parent.doSomething()
        println("ChildOne Do Something")
    }
}

class ChildTwo(val parent: Parent){
    fun doSomething(){
        parent.doSomething()
        println("ChildTwo Do Something")
    }
}

fun main() {

    val parent = Parent()
    val childOne = ChildOne(parent)
    val childTwo = ChildTwo(parent)
    
    childOne.doSomething()
    childTwo.doSomething()
}

// In Java 

public class Parent{
    void doSomething(){
        System.out.println("Do Something");
    }
}
public class ChildOne{
    private Parent parent;
    public ChildOne(Parent parent){
        this.parent = parent;
    }

    void doSomething(){
        parent.doSomething();
        System.out.println("ChildOne Do Something");
    }
}

public class ChildTwo{

    private Parent parent;
    public ChildTwo(Parent parent){
        this.parent = parent;
    }

    void doSomething(){
        parent.doSomething();
        System.out.println("ChildTwo Do Something");
    }
}

public static void main(String[] args) {
    Parent parent = new Parent();
    ChildOne childOne = new ChildOne(parent);
    ChildTwo childTwo = new ChildTwo(parent)
}

In the above code, we refactor our inheritance code to composition: Elementary, no rocket science. Try to compare both if you are not feeling comfortable with this code spend some time.
Now, the next questions are what we lose and what we gain when we change to composition?

What did we lose?

  1. Lose Flexibility -> If I want some method or filed available for ChildOne and ChildTwo, I can add that field or method in Parent class, and then I will get that in all of our inherit classes from Parent. 🙁
  2. Polymorphism -> In our main method, I am not able to enjoy polymorphism because ChildOne now did not inherit from Parent. So If I do a try like Parent parent = new ChildOne() that will not compile.
  3. No more abstraction. I am not able to achieve abstraction; instead, I need to write a concrete code.

What did we achieve?

  1. Gain Flexibility -> If I want to add something in Parent that will not impact my ChildOne and ChildTwo classes. So Parent code is the independent, or maybe a more appropriate case will be If I remove something which is not used in ChildOne and ChildTwo there will be no impact on my code. But in the case of Inheritance, mostly removal of code is painful.
  2. Specific functionality -> In case of composition, if I want to add some functionality that is only specific to ChildTwo but not available to ChildOne, I can add easily by giving that new functionality as a constructor parameter to ChildTwo. In the case of inheritance, we mostly need to add a specific method in Parent class to achieve the Liskov Substitution Principle, and then we need to remember don’t call that method in ChildOne but do override in ChildTwo from where mostly we start losing our control on Inheritance code.

As you can see, Inheritance and Composition are compelling concepts. Still, both can make our code amazing, and both can make our life hell, especially Inheritance, if we do design our classes carelessly. But in the case of Composition, we lose a concept of Polymorphism, which is the foundation of scalable code. I will discuss more this in later posts.
In conclusion, we need to use both; instead, some Design Patterns are using both concepts, and they give us a fantastic power like I will show you this power in the Decorator Pattern post.

Interface:

I am not going to explain to you what an interface is for that you can consult with Google. Instead, I am going to use this interface directly in our code.

I am going to refactor our Inheritance example by using an interface.

interface Base{
    fun doSomething()
}

open class Parent: Base{
    override fun doSomething(){
        println("Do Something")
    }
}

class ChildOne: Parent(){
    override fun doSomething(){
        super.doSomething()
        println("ChildOne Do Something")
    }
}

class ChildTwo: Parent(){
    override fun doSomething(){
        super.doSomething()
        println("ChildTwo Do Something")
    }
}

fun main() {
    var base: Base = Parent()
    base.doSomething()

    base = ChildOne()
    base.doSomething()

    base = ChildTwo()
    base.doSomething()
}

// In Java

public interface Base {
    void doSomething();
}

public class Parent implements Base {
    @Override
    public void doSomething() {
        System.out.println("Do Something");
    }
}

public class ChildOne extends Parent {
    public void doSomething() {
        super.doSomething();
        System.out.println("ChildOne Do Something");
    }
}

public class ChildTwo extends Parent {
    public void doSomething() {
        super.doSomething();
        System.out.println("ChildTwo Do Something");
    }
}

public static void main(String[] args) {
    Base base = Parent();
    base.doSomething();

    base= new ChildOne();
    base.doSomething();

    base = new ChildTwo()
    base.doSomething();
}

The above code is the same as the Inheritance one, only we got one more layer of Abstraction, and in the main method, now Base is the one who is showing the Polymorphic behavior. In this example, I am not able to show you a real power of Interface, but trust in me, interfaces are a fantastic concept, and that can make your code scalable.

Instead, I can show you some power of Interface. Take an example. You are a UI Engineer of some SDK. Now you created a Button class. You are also aware of your Button class will be used by thousands of developers.

Now, you are thinking about how to implement the logic of Button Click because you don’t know what you should do when button click. Like one developer wants when a button is click to execute the logic of logout, other developers want to write the execute login logic on button click. Some other developer wants to start a checkout process when button click. Now, this is the one use case of an interface. When you are not aware of the implementation, but you know you can create some abstraction and provide that abstraction layer to your users. Later you can call their concrete implementations by using your given abstraction as we can see in the below example.

interface Click {
    fun onClick()
}

class Button {

    private var clickListener: Click? = null

    fun setClickListener(click: Click) {
        clickListener = click
    }

    fun onDrawOrSomething() {
        // A lot of Code related to Button UI or internal logic
        clickListener?.onClick()
    }
}

So in the above example, Click interface is in abstraction for your code. You don’t know what developers will implement against this, but now they can use it, and your code is independent of there concrete Implementation.

Now, we are ready to move the Factory Design Pattern.

Factory Design Pattern:

There are many ways how you can achieve this. But we will start from basic.

For example, I have a Parent class and I created an object of that class in my code.

public class Parent{}

public static void main(String[] args) {
    Parent parent = new Parent()
}

Simple, no confusion. By the way, I can create one method in Parent who is responsible for construction of the Parent object as shown below.

public class Parent {

        private Parent(){ }
        
        public static Parent createParent(){
            return new Parent();
        }
}

public static void main(String[] args) {
    Parent parent = Parent.createParent();
}

No difference in the first and second examples.

Now, I have a scenario where I can see the Polymorphism. Like in our example Parent and ChildOne, ChildTwo. In that example Parent is showing us Polymorphism behavior.

public class Parent{ }
public class ChildOne extends Parent{}
public class ChildTwo extends Parent{}

public static void main(String[] args) {
    Parent parent = new ChildOne();
    parent = new ChildOne();
    parent = new ChildTwo();
}

In your code, anywhere, if you can see an Inheritance/Polymorphism, it’s mean you already achieve a 50% Factory Design Pattern use case. Now it’s time to discuss the remaining 50% mean when you should refactor to Factory Design Pattern.

Now I have some specific conditions based on that condition I need to create an object as shown below:

public static void main(String[] args) {
    Parent parent;
    if(args[0] == "One")
        parent = new ChildOne();
    else 
        parent = new ChildTwo();
    
    parent.doSomething();
}

Now, we have achieved the 100% use case of the Factory Design Pattern.

class Factory{
    public static Parent createInstance(String s){
        if(s == "One")
            return new ChildOne();
        else
            return new ChildTwo();
    }
}

public static void main(String[] args) {
    Parent parent = Factory.createInstance(args[0]);
    parent.doSomething();
}

Simple, we achieved the Factory Design Pattern. We can do the same with interfaces.

It’s time to define a cheat sheet definition of the Factory Design Pattern:

  • When we can see Inheritance/Polymorphism in our code. (50%)
  • Inherit class creation depends on some logic or enums. (50%)

From now only we need to remember two things to achieve Factory Design Pattern anywhere. One Inheritance/Polymorphism and second if, else, or enum logic.

Its time to make our self 100% confident about our definition. For that, we will see some examples.

First Example from Java JDK 8.0 Calendar class:

fun main() {
    Calendar.getInstance() // Client Code
}
private static Calendar createCalendar(TimeZone zone,
                                       Locale aLocale)
{
    // I removed a lot of code, so we can only focus on Factory    Pattern

    Calendar cal = null; // Calendar is an abstract class.

    if (aLocale.hasExtensions()) {
        String caltype = aLocale.getUnicodeLocaleType("ca");
        if (caltype != null) {
  
           // Logic on the basis of this we will get the Calendar object
            switch (caltype) {
            case "buddhist":
            cal = new BuddhistCalendar(zone, aLocale);
                break;
            case "japanese":
                cal = new JapaneseImperialCalendar(zone, aLocale);
                break;
            case "gregory":
                cal = new GregorianCalendar(zone, aLocale);
                break;
            }
        }
    }
   // Removed a lot of code
    return cal;
}

Second Example from Java JDK 8.0 NumberFormat class:

fun main() {
    NumberFormat.getInstance(Locale.JAPANESE)
}
private static NumberFormat getInstance(LocaleProviderAdapter adapter,
Locale locale, int choice) {
NumberFormatProvider provider = adapter.getNumberFormatProvider();
NumberFormat numberFormat = null;
switch (choice) {
case NUMBERSTYLE:
numberFormat = provider.getNumberInstance(locale);
break;
case PERCENTSTYLE:
numberFormat = provider.getPercentInstance(locale);
break;
case CURRENCYSTYLE:
numberFormat = provider.getCurrencyInstance(locale);
break;
case INTEGERSTYLE:
numberFormat = provider.getIntegerInstance(locale);
break;
}
return numberFormat;
}

In the above example, Locale will help to create an Object of the NumberFormat inherited class. NumberFormat is an abstract class but that is showing Polymorphic behavior.

Third Example from Android WorkManager library:

public abstract class WorkerFactory {

    public abstract @Nullable ListenableWorker createWorker( 
            @NonNull Context appContext, 
            @NonNull String workerClassName, 
            @NonNull WorkerParameters workerParameters);


    public final @Nullable ListenableWorker createWorkerWithDefaultFallback(
    @NonNull Context appContext,
    @NonNull String workerClassName,
    @NonNull WorkerParameters workerParameters) {

        ListenableWorker worker = createWorker(appContext, workerClassName, workerParameters);
        if (worker == null) {
            // Fallback to reflection
            Class<? extends ListenableWorker> clazz = null;
            try {
                clazz = Class.forName(workerClassName).asSubclass(ListenableWorker.class);
            } catch (ClassNotFoundException e) {
                Logger.get().error(TAG, "Class not found: " + workerClassName);
            }
            if (clazz != null) {
                try {
                    Constructor<? extends ListenableWorker> constructor =
                        clazz.getDeclaredConstructor(Context.class, WorkerParameters.class);
                    worker = constructor.newInstance(
                        appContext,
                        workerParameters);
                } catch (Exception e) {
                    Logger.get().error(TAG, "Could not instantiate " + workerClassName, e);
                }
            }
        }

        if (worker != null && worker.isUsed()) {
            String factoryName = this.getClass().getName();
            String message = String.format("WorkerFactory (%s) returned an instance of a "
                    + "ListenableWorker (%s) which has already been invoked. "
                    + "createWorker() must always return a new instance of a "
                    + "ListenableWorker.",
            factoryName, workerClassName);

            throw new IllegalStateException(message);
        }

        return worker;
    }
}

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:work/workmanager/src/main/java/androidx/work/WorkerFactory.java

If the above code looks complicated, it’s okay you can skip for now. The above example is using the Template Design Pattern with Factory Design Pattern. We will see the Template Design Pattern in future posts.

In the end last example:

interface Base{}

class A: Base
class B: Base
class C: Base

enum class AnyEnum{
    one,two,three
}

object Factory{
    fun create(enum: AnyEnum): Base{
        return when(enum){
            AnyEnum.one -> A()
            AnyEnum.two -> B()
            AnyEnum.three -> C()
        }
    }
}

fun main() {
    Factory.create(AnyEnum.three)
}

Still, you can see the same use case, we have an Inheritance/Polymorphism interface Base, and we have a creation logic that depends on the enum.

Here, Intentionally, I am not giving any Shape or Employee example because I want you should focus on the use case. Anywhere you will see our cheat sheet definition, you should implement this Design Pattern.

Benefits:

We can say, Client code is decoupled, Control of Creation, Code to interface not to the implementation in Client code. Let us do some examples to prove our argument.

Try to assume you are a Client, and you are going to use a third-party library.

Third-party library 1.0.0:

interface Base{}

class A: Base
class B: Base
class C: Base

enum class AnyEnum{
    one,two,three
}

object Factory{
    fun create(enum: AnyEnum): Base{
        return when(enum){
            AnyEnum.one -> A()
            AnyEnum.two -> B()
            AnyEnum.three -> C()
            else -> A()
        }
    }
}

Client Code 1.0.0:

fun something(){
Factory.create(AnyEnum.three)
}

Now, due to some reason in the Library code, we need to change the class C constructor to some platform related value, now we did that change in version 2.0.0

Version 2.0.0:

interface Base{}

class A: Base{}
class B: Base
class C(val isMac: Boolean): Base // Change

enum class AnyEnum{
    one,two,three
}

object Factory{
    fun create(enum: AnyEnum): Base{
        return when(enum){
            AnyEnum.one -> A()
            AnyEnum.two -> B()
            AnyEnum.three -> C(Platform.IsMAC) // Change
        }
    }
}

Client Code 2.0.0: 
fun something(){
    Factory.create(AnyEnum.three) 
} 

As you can see in the above code, there is no change due to library 2.0.0 code changes. It means our client code is decoupled, Control of creation is under the library, and client code is not aware of how the library is creating the objects. In the same way, we can extend our library code by introducing new classes and enums without making any impact on our client’s code.

Conclusion:

In conclusion, I will repeat our cheat sheet Factory Design Pattern Definition.

  • When we can see Inheritance/Polymorphism in our code. (50%)
  • Inherit class creation depends on some logic or enums. (50%)

From, now only we need to remember two things to achieve Factory Design Pattern anywhere. One Inheritance/Polymorphism and second if, else or enum logic.

More Posts on Design Patterns https://www.uwanttolearn.com/design-patterns/



Facebooktwitterredditpinterestlinkedinmailby feather

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.