Pages

Showing posts with label factory. Show all posts
Showing posts with label factory. Show all posts

Wednesday, September 4, 2013

In London you will never be hungry.

I recently arrived to London, I have to say that I am very impressed.
Everything is really beatiful and the weather is great. One of the things that kept my attention is the huge amount of places you can pick for eating. I love food, and while eating at an Indian place at whitechappel yesterday, I've got inspired for my next blog post.

Did your programming teacher ever gave you that exercise, where you had to create a program to pick some food from a restaurant menu and try to apply some design pattern to it?
While looking through the menu at that Indian place I was remembering that homework, and I think it was some kind of factory pattern what we were expected to use back then to solve it.

This article is about the "abstract factory" pattern. Because of its purpose, some people may also refer to it as the "Toolkit pattern".
Let's have a look at it...

The "abstract factory" pattern is an enhancement of the "factory method" pattern(maybe better to say-It uses it...). Let's just refresh quickly our minds about the "factory method" pattern.

The "factory method" pattern is a creational pattern that intents to release the client from the task of creating objects.
The main reasons are:
 -objects may have a complex/dependant initialization mechanism which does not interest the client.
 -the client doesn't know which is the object type that he needs until runtime.

To implement a factory method what we need is create a method that will take an argument(passed at runtime) and add to it conditional logic that will create one object type or other based on the passed parameter.

The only way in which abstract factory differs from factory method is that with abstract factory we just create factories and let the client use the factories for create objects.

Both "abstract factory" and "factory method" are widely used in software engineering. Now let's have look a simple example where an "abstract factory".

In this UML diagram, we see how the client interacts only with the abstract factory and even the objects that creates using those factories are abstract(Food). The client does not know or care at all how those objects are created. As a result, the client call is simplier and does not have complex conditional logic to decide the object that is required.


 public class Customer {  
   public void orderFood() {  
     System.out.println("Which type of food would you like?");  
     Scanner scanner = new Scanner(System.in);  
     System.out.println("1- Mexican");  
     System.out.println("2- Chinese");  
     System.out.println("3- Indian");  
     int option = scanner.nextInt();  
     FoodFactory factory = FactoryMaker.getFactory(option);  
     Food food = factory.prepareFood();  
     System.out.print("Here are your " + food.getClass().getName());  
   }  
 }  
In the above code we see what we just mentioned above. The client using the abstract factory only interacts with abstractions, so there is not much client code.
 public interface FoodFactory {  
   public Food prepareFood();  
 }  
If we want to extend our software and have some other types of factories, we need to implement the comon interface that the client uses to access the factories.
 public class MexicanFoodFactory implements FoodFactory {  
   @Override  
   public MexicanFood prepareFood() {  
     Scanner scanner = new Scanner(System.in);  
     System.out.println("Mexican food menu:");  
     System.out.println("1- Fajitas");  
     System.out.println("2- Tacos");  
     return getFood(scanner.nextInt());  
   }  
   private MexicanFood getFood(int choice) {  
     switch (choice) {  
       case 1:  
         return new Fajitas();  
       case 2:  
         return new Tacos();  
     }  
     return null;  
   }  
 }  
This code above is just one sample implementation of one of those factories. As you can see, it has a "factory method" pattern in itself that will help return the appropiate food object(Just notice that the return type is an abstract class)
 public class FactoryMaker {  
   public static FoodFactory getFactory(int choice) {  
     switch (choice) {  
       case 1:  
         return new MexicanFoodFactory();  
       case 2:  
         return new ChineseFoodFactory();  
       case 3:  
         return new IndianFoodFactory();  
     }  
     return null;  
   }  
 }  
But to allow the client create the factories we will need some kind of gadget that will allow the client create one factory or other at runtime. That is why we need this class called FactoryMaker(This is again another sample of "factory method" but it will return an abstract/interface type)
 public abstract class Food {  
 }  
 public abstract class MexicanFood extends Food {  
 }  
 public class Fajitas extends MexicanFood {  
 }  
This 3 classes above are just part of the domain model.If you want you can make abstract those that you don't need to instantiate using the "new" keyword. The factories task is to create each of the concrete objects but use abstract return types so the client does not know about the type of the object being returned.

 Even if this pattern looks really interesting there are 2 important disadvantages of using it:
 - the bigger the model gets(more products), the more difficult is to maintain.
 - it violates the open-closed principle


Bon Appetit!

Saturday, October 20, 2012

static factory methods, an alternative to public constructors

The most widely used technique to allow other parts of our programs, to get objects of a certain type, is to create public constructors.

1:  public class Product {  
2:        //..  
3:        public Product() {  
4:        }  
5:       //..  
6:  }  

There is also another technique that provides various advantages and it would be highly recommendable for every programmer to know.
Classes can provide static factory methods. This methods are another way of returning instances.

1:  public class Product {  
2:      //..  
3:        private int price;  
4:        private String description;  
5:          
6:          
7:        private Product(int price,String description) {  
8:              this.price = price;  
9:              this.description = description;  
10:        }  
11:        public static Product getNewProduct(int price,String description) {  
12:              return new Product(price,description);  
13:        }  
14:      //..  
15:  }  

This are some of the advantages of using this technique:

Methods have names, so we can be more descriptive when constructing our objects.
Constructors cannot have names, but methods can, so by having this types of methods we can express more fluently how the object is constructed.
So instead of this:

1:  new Product("ProductA",12);   

We can create our objects like this:
1:  Product.getNewProductWithValues("ProductA",12);  

We don't have to create new objects if we don't want to. 
Every time the keyword new is called, a new instance is created. In many occasions, specially in large systems, programmers need to be careful with resources. Some techniques to do that are:
-having cached objects and manage that they are cleaned properly.(Google for Singleton pattern).
-work with immutable objects which provide predefined state.(Google for Builder Pattern)
In the following piece of code you will see a very trivial implementation of a cached object:

1:  public class Product {  
2:        private static Product product = new Product();  
3:        private Product() {  
4:        }  
5:        public static Product getDefaultProduct() {              
6:              return product;  
7:        }  
8:  }  

This type of methods can have a subclass as a return type.
By using this type of methods, we can have big flexibility because we can use sub-classes as return types.
This is a very interesting feature which can allow us to create very powerful factories:

In the following example you can see how the static factory method can be used to create instances of subtypes or implementing types.
:
1:  public final class ProductFactory {  
2:        public static Product getProduct(boolean condition) {  
3:              if(condition) {  
4:                    return new HomeMadeProduct();  
5:              }  
6:              else {  
7:                    return new FactoryMadeProduct();  
8:              }  
9:        }  
10:  }  



  

Share with your friends