Simple Factory in Java and Python
What is a Simple Factory?
The Simple Factory is a programming idiom. It may be mistaken for one of the Design Patterns used in object-oriented programming languages, such as Java, Python, C++, and so on. But no, it is not considered part of those. Still, it is quite commonly used and therefore it is also worth mentioning.
So what is this so-called programming idiom used for? The answer to that is rather simple! It is used to encapsulate the creation of objects. This means that the instantiation of different objects is done in a different place of where it is accessed and used. In order for this to work, a new class is created that will be handling the object creation. This class also publishes a method for creating the object. This should contain "create" somewhere within its name so that developers using this method know what they are about to do. The Create method should also have a parameter for it to determine what object it is supposed to create.
The advantage of putting the Simple Factory into practice is to decouple the client code from the details of the object creation. The only thing the client needs to do is ask for the desired object, and he does not need to know the exact implementation. Another advantage is that there is a central place for that needs to be adapted when the created objects are changed in their structure. Instead of changing every part in the code where the object would be created it is not only the new creation class that needs to be worked on. Also, testing becomes easier with this structure as mock implementation just needs to be added within the creation class and not everywhere across the entire application.
What is the structure of a Simple Factory?
- Product Definition
The general object that needs to be created needs a definition of what it generally does. This should be hand in hand with the idea of what it is supposed to do. In this example we want it to do an operation(), but we do not yet define what exactly the operation will be as this would be the place for classes that implement the Product definition. Those classes would be Product1 and Product2. Those are the classes that will actually be created. - Factoy Object
Within the creation class that we called ProductFactory is a method which we called createProduct(type: String). This method takes a String to decide what object it will create.
Example Codes
There are a number of programming languages where the Simple Factory can prove useful. Every language that supports the construct of classes can make use of this programming idiom.
Java Example
The following example is a Java application putting the Simple Factory into action. All the following files need to be placed into the same folder so that the code within the files can work properly, because the files also reference each other. As this is the smallest possible code example, this little project only consists of five Java files: Product.java, Product1.java, Product2.java, ProductFactory.java, and Main.java.
public interface Product {
void operation();
}
public class Product1 implements Product {
@Override
public void operation() {
System.out.println("Operation of Product 1");
}
}
public class Product2 implements Product {
@Override
public void operation() {
System.out.println("Operation of Product 2");
}
}
public class ProductFactory {
public static Product createProduct(String productType) {
if (productType.equals("Product1")) {
return new Product1();
} else if (productType.equals("Product2")) {
return new Product2();
}
return null;
}
}
public class Main {
public static void main(String[] args) {
System.out.println("Simple Factory in Java");
System.out.println("----------------------");
System.out.println();
Product product1 = ProductFactory.createProduct("Product1");
Product product2 = ProductFactory.createProduct("Product2");
product1.operation();
product2.operation();
}
}
There also needs to be a Manifest.txt file within the same folder. This is a metadata file used primarily in JAR files. It contains information about the JAR file itself and its contents. It is placed within thie META-INF folder within the JAR archive file strucutre.
Main-Class: Main
To compile this code into an executable Java application which would be a JAR file, a couple of commands need to be executed from within the same directory. The commands are found within the build file.
@echo off
javac *.java
jar cvfm SimpleFactoryDemo.jar Manifest.txt *.class
#!/bin/bash
javac *.java
jar cvfm SimpleFactoryDemo.jar Manifest.txt *.class
Now that the compilation has taken place, there are new files within the same directory. Every JAVA file has its equivalent CLASS file, and there is also a file called SimpleFactoryDemo.jar. This is the Java application that needs to be executed. The command for that is within the run file.
@echo off
java -jar SimpleFactoryDemo.jar
#!/bin/bash
java -jar SimpleFactoryDemo.jar
Testing the Java Example
Now that all the files are ready and within their correct location they can be put to test. First we need to compile the Java code and then we can execute it to see what it will print in the Windows Command Prompt or in the MacOS / Linux Terminal.
Python Example
The following example is a Python application putting the Simple Factory into action. All the following files need to be placed into the same folder so that the code within the files can work properly, because the files also reference each other. As this is the smallest possible example, this little project consists of five Python files:
- product.py
- product_1.py
- product_2.py
- product_factory.py
- main.py
from abc import ABC, abstractmethod
class Product(ABC):
@abstractmethod
def operation(self):
pass
from product import Product
class Product1(Product):
def operation(self):
print("Operation of Product 1")
from product import Product
class Product2(Product):
def operation(self):
print("Operation of Product 2")
from product_1 import Product1
from product_2 import Product2
class ProductFactory:
@staticmethod
def createProduct(productType):
if productType == "Product1":
return Product1()
elif productType == "Product2":
return Product2()
return None
from product_factory import ProductFactory
def main():
print("Simple Factory in Python")
print("------------------------")
print()
product1 = ProductFactory.createProduct("Product1")
product2 = ProductFactory.createProduct("Product2")
product1.operation()
product2.operation()
if __name__ == "__main__":
main()
There is no need to compile anything in Python. The code is executed directly using the python command under Windows and the python3 command under MacOS / Linux.
Testing the Python Example
Now that all the files are ready and within their correct location they can be put to test. Python does not need to be compiled before being run. Therefore we can execute it right away to see what it will print in the Windows Command Prompt or in the MacOS / Linux Terminal.
More Information
So, where do I have my information from? In general, there are lots of places on the internet that offer great information. But that is just one source of information. Another source would be books. Those have the advantage that usually several people work on the same book before it is released, raising the chance for distribution of good and proven information.
Head First - Design Patterns
Building Extensible and Maintainable Object-Oriented Software
A book that has proven to be a valuable asset within my personal library is Head First - Design Patterns by the publisher O'Reilly. It has a fun approach to this topic, having recurring characters, such as the Guru, the Developer, the Skeptical Developer, Joe, and many more.
Java Design Patterns
A Hands-On Experience with Real-World Examples
Another highly valuable book is Java Design Patterns: A Hands-On Experience with Real-World Examples by the publisher Apress. It offers a conservative and rather scientific approach to the subject. It also offers code examples in Java, although any object-oriented programming language applies to the design patterns shown here.