I'm new to OOP and learning design patterns so I wrote some simple code to try out a Factory Method, and all seems well, except when I want to add another sub-type. Here's the code so far:
public interface Person {
public String getDescription();
}
public class Adult implements Person {
@Override
public String getDescription() {
return "I am an ADULT";
}
}
public class Child implements Person {
@Override
public String getDescription() {
return "I am a CHILD";
}
}
public class PersonFactory {
public Person create(int age) {
if (age < 18) return new Child();
return new Adult();
}
}
public class ClientA {
public static void main(String[] args) {
PersonFactory personFactory = new PersonFactory();
Person person;
person = personFactory.create(80);
System.out.println(person.getDescription());
}
}
If the requirement changes later to include a sub-class Pensioner
for when the age is > 70, I would have to either:
Add the line if (age > 70) return new Pensioner();
to the create()
method in the PersonFactory
class, which surely breaks the Open-Closed Principle?
Or, as suggested in The Gang Of Four Design Patterns book, override the parameterized factory method to selectively extend the products a Creator produces. In this case I think that would mean writing a new class:
public class PersonFactoryWithPensioner extends PersonFactory {
@Override
public Person create(int age) {
if (age > 70) return new Pensioner();
return super.create(age);
}
}
This now means that either all the clients which call the PersonFactory
would now have to be changed to use PersonFactoryWithPensioner
instead, or I have to accept that new clients could call PersonFactoryWithPensioner
whilst the old clients eg. ClientA
would still only receive an Adult
object when the age is > 70. It gets even worse if later on another sub-class eg. Infant
is added. To ensure the new clients receive whichever object of Infant
, Child
, Adult
or Pensioner
is appropriate, a new class PersonFactoryWithInfant
would have to extend PersonFactoryWithPensioner
. This can't be right, seems more likely I have misunderstood what GoF suggest.
My question is: Is there a way to add a new sub-type that can be returned to old clients without changing them, and without breaking the OCP by changing the PersonFactory
code to include the new sub-type?
Apologies if I have not posted this correctly, it is my first time posting a question here. I have looked through previous answers for similar problem but they don't seem to quite address this.