Factory Method Pattern Example in Java troubles

12,407

Solution 1

In brief there are several issues in your version that were corrected below:

  1. createPerson method is useless.
  2. The way you invoke the factory method is wrong.
  3. You use == instead of .equals in your factory method.

I've enhanced your Person class to add a member field that is shared by the Male and Female class, to demonstrate how sharing a common abstract constructor could be used.

public abstract class Person {   
    protected final String name;
    public Person(String name) { 
        this.name = name;
    }
}

public class Male extends Person {
    public Male(String name) { 
        super(name);
    }
}

public class Female extends Person {
    public Female(String name) { 
        super(name);
    }
}

public class PersonFactory
{
     public static Person makePerson(String gender, String name) 
     {
         if(gender.equals("male"))                       
         { 
             Male man=new Male(name);
             return man;
         }
         else
         {
             Female woman=new Female(name);
             return woman;
         }
     }
}

public class Test 
{
    public static void main(String[] args)
    {
       Person y= PersonFactory.makePerson("male", "bob"));
       Person z= new PersonFactory.makePerson("female", "janet"));
    }
}

Solution 2

Should be:

public class Test 
{
    public static void main(String[] args)
    {
       Person y= PersonFactory.makePerson("male");  
       Person z= PersonFactory.makePerson("female");
    }
}

The reason it is

PersonFactory.makePerson("male")

is because you have a static method makePerson (which means you do not have to 'new' a class to call the method as it is not an instance method) i.e. a static variable in a class is available to all instances of a class. A static method is called TheClassItIsDefinedIn.TheMethodSignature

Additionally:

public abstract class Person 
{   
    public void createPerson(){ }
}

should really be an interface as you have no functional code that is shared between derived types (well not shown here any way) and here is a laymans explanation of abstract and interface:

interface: A contract that states 'I have method blah and blah2 so any class implementing me must have a method of that name and signature (and it can have whatever code it likes in there as long as it matches the return type etc)'

abstract: an abstract class can have method signatures just like an interface BUT it also would usually have concrete implementations that are generic amongst all deriving types

Solution 3

I would recommend you get a grip in java programming before starting to apply design patterns. Design patterns normally require OO principles, and as such would not make any much sense if you lack good programming practices.

Nonetheless, the definition of your Factory method looks right in the context of the meaning but not in usability. The Factory Method needs to create an object, and hence return a reference to the created object. Furthermore, the created object is usually different from the class that implements the Factory Method pattern, since it is envisaged that the created instance is to be used by object, in this case Person.

So here is an abstract example of probably how you may use the factory pattern.

  public abstract class Student {
  }

  public class PrimarySchoolStudent extends Student {
  }

  public class HighSchoolStudent extends Student {
  }

  public abstract class ClassRoom {

    private List<Student> students;

    void enrollStudent(String studentId) {
      Student student = newStudent();
      students.add(student);
    }

    abstract Student newStudent();
  }

  public class HighSchoolClassRoom extends ClassRoom {

    @Override
    Student newStudent() {
      return new HighSchoolStudent();
    }
  }

  public class PrimarySchoolClassRoom extends ClassRoom {

    @Override
    Student newStudent() {
      return new PrimarySchoolStudent();
    }
  }

Solution 4

Complete example based on @maress' code :

import java.util.ArrayList;
import java.util.List;

abstract class Student {
    private int StudentID;

    public Student() {
    }

    public Student(int _studentId) {
        this.StudentID = _studentId;
    }

}

class PrimarySchoolStudent extends Student {

    public PrimarySchoolStudent() {
    }

    public PrimarySchoolStudent(int _studentId) {
        super(_studentId);
    }
}

class HighSchoolStudent extends Student {

    public HighSchoolStudent() {
    }

    public HighSchoolStudent(int _studentId) {
        super(_studentId);
    }
}

abstract class ClassRoom {
    private List<Student> students;

    public void enrollStudent(int studentId) {
        if (students == null)
        {
            students = new ArrayList<Student>();
        }
        Student student = newStudent(studentId);
        students.add(student);
    }

    abstract Student newStudent(int studentId);
}

class HighSchoolClassRoom extends ClassRoom {

    @Override
    Student newStudent(int studentId) {
        return new HighSchoolStudent(studentId);
    }
}

class PrimarySchoolClassRoom extends ClassRoom {

    @Override
    Student newStudent(int studentId) {
        return new PrimarySchoolStudent(studentId);
    }
}

public class RunCode {
    public static void main(String[] args) {

        ClassRoom cr_highSchool = new HighSchoolClassRoom();
        cr_highSchool.enrollStudent(1234);
        cr_highSchool.enrollStudent(5678);
        cr_highSchool.enrollStudent(1938);
        cr_highSchool.enrollStudent(7465);
    }
}
Share:
12,407
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm trying to create a really simple Factory Method design pattern example in Java. I don't really know Java, I am new to programming in general but I need to come up with a a basic FactoryMethod example implemented in java. The following is what I came up with. There are quite a few errors I'm sure, I'm missing some constructors apparently and I get confused with abstract classes and interfaces. Could you point out my mistakes and correct my code along with an explanation please? Thank you in advance for your time and help.

    public abstract class Person 
    {   
        public void createPerson(){ }
    }
    
    public class Male extends Person 
    {   
        @Override
        public void createPerson() 
        {
            System.out.print("a man has been created");
        }
    }
    
    public class Female extends Person 
    {   
        @Override
        public void createPerson() 
        {
            System.out.print("a woman has been created");
        }
    }
    
    public class PersonFactory
    {
         public static Person makePerson(String x) // I have no Person constructor in
         {                                         // the actual abstract person class so 
             if(x=="male")                         // is this valid here?
             { 
                 Male man=new Male();
                 return man;
              }
              else
             {
                 Female woman=new Female();
                 return woman;
             }
         }
    }
    
    
    public class Test 
    {
        public static void main(String[] args)
        {
           Person y= new Person(makePerson("male"));   // definitely doing smth wrong here
           Person z= new Person(makePerson("female")); // yup, here as well
        }
    }