What is the most usual method of creating an instance of a class in java? Most people will answer this question: “using new keyword“. Well, it is considered old fashioned now. Lets see how??
If object creation code is spread in whole application, and if you need to change the process of object creation then you need to go in each and every place to make necessary changes. After finishing this article, while writing your application, consider using factory pattern.
In this post, I will demonstrate another creational pattern, i.e. Factory pattern, for creating instances for your classes. Factory, as name suggest, is a place to create some different products which are somehow similar in features yet divided in categories.
The Factory pattern provides a way to use an instance as a object factory. The factory can return an instance of one of several possible classes (in a subclass hierarchy), depending on the data provided to it.
In java also, factory pattern is used to create instances of different classes of same type.
Where to use:
- When a class can't anticipate which kind of class of object it must create.
- You want to localize the knowledge of which class gets created.
- When you have classes that is derived from the same sub-classes, or they may in fact be unrelated classes that just share the same interface. Either way, the methods in these class instances are the same and can be used interchangeably.
- When you want to insulate the client from the actual type that is being instantiated.
Implementation:
In this example, we'll create a simple "dog factory" that can return a variety of Dog types, where the "Dog" that is returned matches the criteria we specify. For instance, we might tell our factory that we want a small dog, or a large dog, and the dog factory will give us a dog of the type we asked for.
The idea for this article isn't to get too deep into the theory of the factory pattern, but instead, to demonstrate a Java factory pattern example.
The Dog interface
First, we'll create a Dog interface. Any dog that our factory returns must implement this Java interface, so for the purposes of our example, we'll keep this interface very simple. We'll just specify that any class that calls itself a Dog must implement a speak method that looks like this:
First, we'll create a Dog interface. Any dog that our factory returns must implement this Java interface, so for the purposes of our example, we'll keep this interface very simple. We'll just specify that any class that calls itself a Dog must implement a speak method that looks like this:
package com.learnjavaj2ee.factory; public interface Dog { public void speak (); }
The concrete Dog classes:
Next, we'll define a few concrete classes that implement our Dog interface. Keeping with our simple interface, each class implements the speak method, but implements it in a slightly different way that befits each dog type:
Next, we'll define a few concrete classes that implement our Dog interface. Keeping with our simple interface, each class implements the speak method, but implements it in a slightly different way that befits each dog type:
package com.learnjavaj2ee.factory; public class Poodle implements Dog { public void speak() { System.out.println("The poodle says \"arf\""); } }
package com.learnjavaj2ee.factory; public class Rottweiler implements Dog { public void speak() { System.out .println("The Rottweiler says (in a very deep voice) \"WOOF!\""); } }
package com.learnjavaj2ee.factory; public class SiberianHusky implements Dog { public void speak() { System.out.println("The husky says \"Dude, what's up?\""); } }
As you can see from the code, each of these concrete classes (Poodle, Rottweiler, and SiberianHusky) implements our Dog interface. This is a key point, and an important part of the Factory Pattern:
You define a base class type (or in this case an interface), and then have any number of subclasses which implement the contract defined by the base class.
And as you're about to see, the signature of the factory method shows that it will be returning a class which implements our base class, in this case, our Dog interface.
The Java Factory class
Next we'll define our Java Factory class, which in this case is a DogFactory class. As you can see from the code below, the DogFactory class has a static getDog method that returns a "Dog" depending on the criteria that has been supplied.
Next we'll define our Java Factory class, which in this case is a DogFactory class. As you can see from the code below, the DogFactory class has a static getDog method that returns a "Dog" depending on the criteria that has been supplied.
package com.learnjavaj2ee.factory; public class DogFactory { public static Dog getDog(String criteria) { if (criteria.equals("small")) return new Poodle(); else if (criteria.equals("big")) return new Rottweiler(); else if (criteria.equals("working")) return new SiberianHusky(); return null; } }
Also, it's very important to note that in this simple example I'm only accepting strings like "small", "big", and "working" as my "criteria". In a more complicated (real world) example, you'll want to tighten down this code much more.
The Java Factory pattern example program
Now that we've created our dog factory, our Dog interface, and all of our dog types, we'll create a "driver" program named JavaFactoryPatternExample to test our Dog factory. This driver class demonstrates how to get different types of dogs from the factory:
Now that we've created our dog factory, our Dog interface, and all of our dog types, we'll create a "driver" program named JavaFactoryPatternExample to test our Dog factory. This driver class demonstrates how to get different types of dogs from the factory:
package com.learnjavaj2ee.factory; public class JavaFactoryPatternExample { public static void main(String[] args) { // create a small dog Dog dog = DogFactory.getDog("small"); dog.speak(); // create a big dog dog = DogFactory.getDog("big"); dog.speak(); // create a working dog dog = DogFactory.getDog("working"); dog.speak(); } }
As you can see from our driver class, we create an instance of each type of dog (small, big, and working).
Advantages of factory pattern:
- By now, you should be able to count the main advantages of using factory pattern. Lets note down:
- The creation of an object precludes its reuse without significant duplication of code.
- The creation of an object requires access to information or resources that should not be contained within the composing class.
- The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.
- The client does not need to know every subclass of objects it must create. It only need one reference to the abstract class/interface and the factory object.
- The factory encapsulate the creation of objects. This can be useful if the creation process is very complex.
Drawbacks/consequences:
There is no way to change an implementing class without a recompile.
There is no way to change an implementing class without a recompile.
Final Notes:
Factory pattern is most suitable where there is some complex object creation steps are involved. To ensure that these steps are centralized and not exposed to composing classes, factory pattern should be used. We can see many examples of factory pattern in JDK itself e.g.
java.sql.DriverManager#getConnection()
java.net.URL#openConnection()
java.lang.Class#newInstance()
java.lang.Class#forName()
java.net.URL#openConnection()
java.lang.Class#newInstance()
java.lang.Class#forName()
0 comments:
Post a Comment