The factory pattern is a creational design pattern that provides an abstraction for creating objects. It encapsulates the object creation process and lets subclasses decide which class to instantiate. This pattern promotes loose coupling between classes and simplifies object creation.
Benefits of using the factory method pattern
- Encapsulation of object creation: The factory method pattern encapsulates the object creation logic, making it easier to change the type of object created without modifying the client code.
- Code reusability: The factory method pattern allows for code reusability by defining an abstract factory method that can be implemented by subclasses to create different product types.
- Dynamic object creation: The factory method pattern facilitates dynamic object creation, enabling subclasses to decide which class to instantiate based on runtime conditions or user input.
Implementation of the factory method pattern
- Define an interface or abstract class for creating objects: This interface or abstract class declares a factory method that takes parameters and returns an instance of a product class.
- Implement the factory method in concrete classes: Each concrete class inherits from the abstract class and provides its own implementation of the factory method. The implementation determines the type of product instance that is created.
Athletes application examples
Create an enum class for the sport type
public enum SportType {
JUDO,
RUNNER,
WEIGHTLIFTING
}
Athlete Abstract Class
public abstract class Athlete {
private int strength;
private int speed;
private int endurance;
public Athlete(int strength, int speed, int endurance) {
this.strength = strength;
this.speed = speed;
this.endurance = endurance;
}
public int getStrength() {
return strength;
}
public int getSpeed() {
return speed;
}
public int getEndurance() {
return endurance;
}
}
Extending athletes class
public class JudoFighter extends Athlete{
public JudoFighter(int strength, int speed, int endurance) {
super(strength, speed, endurance);
}
}
public class Runner extends Athlete{
public Runner(int strength, int speed, int endurance) {
super(strength, speed, endurance);
}
}
public class Weightlifter extends Athlete {
public Weightlifter(int strength, int speed, int endurance) {
super(strength, speed, endurance);
}
}
AthleteFactory Abstract Class
abstract public class AbstractFactory {
abstract public Weightlifter createWeightlifter(SportType type);
abstract public Runner createRunner(SportType type);
abstract public JudoFighter createJudoFighter(SportType type);
}
Extending AthleteFactory class
public class AthleteFactory extends AbstractFactory {
@Override
public Weightlifter createWeightlifter(SportType type) {
switch (type) {
case WEIGHTLIFTING: {
return new Weightlifter(90, 12, 10);
}
default:
throw new UnsupportedOperationException("Selected athlete not exist");
}
}
@Override
public Runner createRunner(SportType type) {
switch (type) {
case RUNNER: {
return new Runner(10, 90, 20);
}
default:
throw new UnsupportedOperationException("Selected athlete not exist");
}
}
@Override
public JudoFighter createJudoFighter(SportType type) {
switch (type) {
case JUDO: {
return new JudoFighter(70, 60, 70);
}
default:
throw new UnsupportedOperationException("Selected athlete not exist");
}
}
}
Create objects from specific classes
public class Main {
public static void main(String[] args) {
AthleteFactory athleteFactory = new AthleteFactory();
Athlete judoFighter = athleteFactory.createJudoFighter(SportType.JUDO);
Athlete weightLifter = athleteFactory.createWeightlifter(SportType.WEIGHTLIFTING);
Athlete runner = athleteFactory.createRunner(SportType.RUNNER);
}