Factory Pattern

By | August 7, 2016 | 112 Views

Factory Pattern is to create object through a common interface/ abstract class. It belongs to Creational Pattern group.

1. Real-life example

Suppose that we have two different types of instruments in capital market – one with an Equities and another with a Dept. A company want to use an instrument to raise capital, and represents a direct investment in the ownership of the company. They will use Equities (Shares). In other cases, companies or governments do not imply any right of ownership of the issuing entity but rather represent a set of cash flows on terms to which the lender and borrower agree. The dept instrument is used to borrow funds basing on pay/re-pay interest.

2. Solution

As a company or investor, they need a way of creating different final instruments: Equity, Dept, and so on. The factory design pattern allows us to create objects without exposing the instantiation logic business to client.

2.1 Class Diagram

Factory Pattern
Figure 1: Instrument UML Class Diagram.

How to apply OO Principle?

  • Dependency Inversion Principle: High Level Classes –> Abstraction Layer –> Low Level Classes. Particularly, High-level modules should not depend on low-level modules. Both should depend on abstractions. If we have other components that use the factory to get instruments for their trading. So we use the CapitalMarketFactory abstract class to do this instead of the concrete class.
  • Open Close Principle: Classes, modules and functions should be open for extension but closed for modifications. So, by encapsulating the instrument creating one class, we now only one place to make modification when the implementation changes. The factory method (createInstrumentType method) is the key to encapsulate the information.

3. Implementation

3.1 Instrument.java: an instrument interface.

public interface Instrument {
    String getInstruction();
}

Noticeable that the instrument “interface” is a general use of phrase, a concrete class implementing a method from a super-type (it could be a class, abstract class , or interface) is still considered to be “implementing the interface” of that super-type.
3.2 Dept.java

public class Debt implements Instrument {
    @Override
    public String getInstruction() {
        return Type.DEBT + " Company raise capital by " 
                         + "loading fund from investors.";
    }
}

3.3 Equities.java

public class Equities implements Instrument {
    @Override
    public String getInstruction() {
        return Type.EQUITIES + " are issued by companies " 
                             + " to raise capital.";
    }
}

3.4 CapitalMarketFactory.java: Abstract Factory

public abstract class CapitalMarketFactory {
    public abstract Instrument createInstrumentType(Type type)
                                             throws Exception;
}

3.5 ConcreteCapitalMarketFactory.java: Concrete Factory

public class ConcreteCapitalMarketFactory extends CapitalMarketFactory {
    @Override
    public Instrument createInstrumentType(Type type) throws Exception {
       if (Type.EQUITIES.equals(type)){
           return new Equities();
       } else if (Type.DEBT.equals(type)){
           return new Debt();
       } else {
           throw new RuntimeException("No such instrument type " + type);
       }
    }
}

3.6 FactoryMainTest.java

public class FactoryMainTest {
    public static  void main(String[] args) throws Exception{
        CapitalMarketFactory capitalMarketFactory = new ConcreteCapitalMarketFactory();
        Instrument equitiesType = capitalMarketFactory
                                       .createInstrumentType(Type.EQUITIES);
        System.out.println(equitiesType.getInstruction());

        Instrument debtType = capitalMarketFactory
                                       .createInstrumentType(Type.DEBT);
        System.out.println(debtType.getInstruction());

        //There is no DERIVATIVES type. So, an exception will be thrown
        Instrument derivativesType = capitalMarketFactory
                                       .createInstrumentType(Type.DERIVATIVES);
        System.out.println(derivativesType.getInstruction());
    }
}

Output in console:

EQUITIES are issued by companies to raise capital.
DEBT Company raise capital by loading fund from investors.
Exception in thread "main" 
java.lang.RuntimeException: No such instrument type DERIVATIVES
...

4. Improvement with lambda

Using the same technique, we will rewrite the previous code by creating a Map that maps a instrument type to its constructor. Then we can use this Map to instantiate different instruments as we did with the factory design pattern.

4.1 CapitalMarketFactory.java

public abstract class CapitalMarketFactory {
    public abstract Instrument createInstrumentTypeLambda(Type type)
                                                  throws Exception;
}

4.2 ConcreteCapitalMarketFactory.java

@Override
    public Instrument createInstrumentTypeLambda(Type type) throws Exception {
        Supplier<Instrument> p = map.get(type);
        if(p != null) return p.get();
        throw new RuntimeException("No such instrument type " + type);
    }

    final private Map<Type, Supplier<Instrument>> map = new HashMap<>();
    {
        map.put(Type.DEBT, Debt::new);
        map.put(Type.EQUITIES, Equities::new);
    }

4.3 FactoryMainTest.java

 public static  void main(String[] args) throws Exception{
        CapitalMarketFactory capitalMarketFactory = new ConcreteCapitalMarketFactory();
        Instrument equitiesType = capitalMarketFactory
                                        .createInstrumentTypeLambda(Type.EQUITIES);
        System.out.println(equitiesType.getInstruction());

        Instrument debtType = capitalMarketFactory
                                        .createInstrumentTypeLambda(Type.DEBT);
        System.out.println(debtType.getInstruction());

        //There is no DERIVATIVES type. So, an exception will be thrown
        Instrument derivativesType = capitalMarketFactory
                                        .createInstrumentTypeLambda(Type.DERIVATIVES);
        System.out.println(derivativesType.getInstruction());
}

Output is the same with the previous output.
Download zip here

Correction: Factory Pattern is divided into two types: Abstract Factory and Factory Method.

References:

  1. Vaskaran Sarcar,”Factory Method Patterns”, In Java Design Pattern, pp.73-76, Chap.12, Apress Media, 2016.
  2. Raoul-Gabriel Urma, Mario Fusco, and Alan Mycroft, “Refactoring, testing, and debugging”, In Java 8 in Action, pp.234-261, Chap.8, Manning Publications, 2015.
  3. Factory Method Pattern, Design Patterns. Accessed at http://www.oodesign.com/factory-method-pattern.html on August 08, 2016.

Leave a Reply

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