Friday, April 29, 2005

Factory Pattern

I have been reading lately about the Factory design pattern in Java. Most of the text i read in web describes what Factory pattern is but not HOW to use the design pattern? Or describe how it helps in future changes to your application . I felt a need to add a note on it on my first blog here.

How to use a Factory Design Pattern ? How it helps in future changes to your application? Use Case (Where to use? - Think about a requirement where you need to create documents. Your application uses a document object . You can have methods like - read(),write() methods or any other methods u need in document object. But there are different ways (implementation) u can create a document object. For example creating a document object from a file, from an input stream. But its not limited to only these 2 implementations. There could be other ways to create document like getting it from other application etc. So you want to develop your application such that it has 2 implementation of creating a document and support future implementation of document creation.

Here is how your client application should look like.

public class DocumentUser
{
Document doc ;
DocumentFactory docFactory ;
public Document getDocument()
{
return doc;
}

public void setDocument()
{
return docFactory.createDocument();
}

public void setDocFactory(DocumentFactory docFactory)
{
this.docFactory = docFactory;
}

public static void main()
{
DocumentUser docUser = new DocumentUser();
DocumentFactoryFile docFactory = new DocumentFactoryFile();
//DocumentFactoryStream docFactory = new DocumentFactoryStream();
docUser.setDocumentFactory(docFactory);

Document doc = docUser.getDocument();
doc.read();

}
}


In the above class we havent actually created the document object inside the DocumentUser, instead have moved the actual instantiation to the DocumentFactory classes. And we have made the DocumentFactory object as a class variable of the DocumentUser object. In doing the above 2 changes we have made our DocumentUser classs independent of the Document Creation implementation. You can add or change any document implementation to the DocumentUser (as shown in the main method - just uncomment the commented line and comment the upper line.) So now your application(DocumentUser) is independent of Document creation or implementation.

How to implement Factory Design Pattern?
So now since you know how to use factory design pattern , you can go ahead and create your first implementation of Factory Design Pattern. There are lot information in the web to explain how to create the Factory design pattern, but just for your convinience and my reference i am writing the next block.
There are basically 2 ways to implement the Factory Design pattern.
1) Concrete Class
In this implementation you create a BaseFactory Class. Have a create() method with default implementation. Then any sub classes extending from the BaseFactory class can over-ride the create method if needed. Else it will use the default implementation of the BaseFactory Class. This implementation is used when you know the default implementation of the object creation.

public class BaseDocumentFactory
{
public Document createDocument()
{
return new DocumentBase();
}
}


public class DocumentFactoryFile extends DocumentFactory
{
public Document createDocument()
{
return new DocumentFile();
}
}
public class DocumentFile implements Document
{
...
...
...

public String read()
{
System.out.println("File Implementation of document.");
}

}

public class DocumentBase implements Document
{
...
...
...

public String read()
{
System.out.println("Base Implementation of document.");
}
}


2) Abstract Class
In this implementation you create an abstract class with an abstract method ex - create() . The classes extending from the the abstract class actually does the creations of the object. This type of implementation should be used when the base class is not aware of the implementation ans there is no default implementation .

public abstract class DocumentFactory
{
public abstract Document createDocument();
}

public class DocumentFactoryFile extends DocumentFactory
{
public Document createDocument()
{
return new DocumentFile();
}
}

public class DocumentFile implements Document
{
...
...
...


public String read()
{
System.out.println("File Implementation of document.");
}
}


Well you must be thinking cant we use an "Interface" and all Factory Classes must implement the create method. Answer - Yes you can. I think its just a variant of the Abstract Class type.


-ANY COMMENT IS APPRECIATED!!!!!

No comments: