Monday, November 16, 2015

Head First Design Pattern CH4: Factory and Abstract Factory Patterns

 in this chapter we talk about Factory Pattern and Abstract Factory Pattern. we will not use the examples given in this chapter, we will just write some notes from it
 

 The idea here that creating object should be a responsibility of a single class,  we dont wanna see new() statments everywhere.

 they talked here about Dependency Inversion Principle, in order to achieve it you should always try to follow this:
 1- you should never have a variable that has a reference to a concrete class (if you use new(), it means that you are
 using a reference to a concrete class, get around that by using the Factory pattern)
 2- you should never have a class that extends a concrete class( only extend from abstract class or implement an interface)
 3- No method should override an implemented method of any of its base classes(if you override an implemented method, then your base
 class wasnt really an abstraction to start with)
 
In Factory Pattern, we will have a class with a specific method to create objects, for example lets consider the following:


we have different shapes here, we will add a Factory to create shapes

as you can see the creation of Shapes is totally seperated from their behaviour, they dont even know how they are created.

ShapeFactory class looks like this:

and if you wanna create a shape you write this.


as you can see the Factory Pattern creates an object of a single class (you will have a Factory class for each Interface), however sometimes you need to create multiple related object together. For example, lets say we have the following:


as you can see we have IProcessor and IRam interfaces,

we have 2 factories one to create a fast computer and another one to create slow computer, as you can see creating a computer means creating ram and processor.

FastComputerFactory knows that it should create CoreI7 processor and DDR3 ram
SlowComputerFactory will create CoreI3 and DDR1.

The AbstractComputerFactory has 2 methods one to getProcessor() and another one to getRam()

The code looks like this:


public interface IProcessor {void PerformOperation();}
public class CoreI7 : IProcessor
{
    public void PerformOperation()
    {
        Console.WriteLine("Operation will perform quickly");
    }
}
public class CoreI3 : IProcessor
{
    public void PerformOperation()
    {
        Console.WriteLine("Operation will perform Slowly");
    }
}


public interface IRam { void StoreData(); }
public class DDR3 : IRam 
{
    public void StoreData()
    {
        Console.WriteLine("Data will take less time to store");
    }
}
public class DDR1: IRam 
{
    public void StoreData()
    {
        Console.WriteLine("Data will take more time to store");
    }
}

public interface AbstractComputerFacotry
{
    IProcessor getProcessor();
    IRam getRam();
}
public class FastComputerFactory : AbstractComputerFacotry
{
    public  IProcessor getProcessor() { return new CoreI7(); }
    public IRam getRam() { return new DDR3(); }
}
public class SlowComputerFactory : AbstractComputerFacotry
{
    public  IProcessor getProcessor() { return new CoreI3(); }
    public IRam getRam() { return new DDR1(); }
}

As you can see in the picture we have a FactoryProducer, basically this is a producer of slow or fast computer

public class FactoryProducer {
   public static AbstractComputerFacotrygetFactory(String choice){
   
      if(choice.equalsIgnoreCase("Fast")){
         return new FastComputerFactory ();
         
      }else if(choice.equalsIgnoreCase("Slow")){
         return new SlowComputerFactory ();
      }
      
      return null;
   }
public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
      AbstractComputerFacotry computerFactory = FactoryProducer.getFactory("Fast");
      IProcessor processor = computerFactory.getProcessor();
      IRam ram = computerFactory.getRam();      
   }
}

No comments:

Post a Comment