5

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
    }
}
Jens Björnhager
  • 5,632
  • 3
  • 27
  • 47
  • There's an implicit, parameterless `new` for classes unless you define a constructor with parameters. – Dave Newton May 12 '12 at 20:43
  • 1
    "... and correct my code along with an explanation please?" this is not a Homework correction service. Please show us any compilation errors and describe any behavioral problems. The onus of effort here should be *yours*. – Hovercraft Full Of Eels May 12 '12 at 20:44
  • 2
    @Hovercraft Full Of Eels this is not a homework. I'm studying for exams and I need to study the FactoryMethod design pattern. The internet is full with Java examples which I find unnecessarily complicated. I'm not trying to "cheat" I'm trying to learn that's why I've provided you with code that I wrote but which is not working. –  May 12 '12 at 20:48
  • It's not a matter of cheating but rather a matter of you really should not try to make it difficult for others to help, and you should show more effort. You should post your error messages, you should take the effort to try to debug your code and show the results of this effort. It's only right to do this if you're asking for free advice. – Hovercraft Full Of Eels May 12 '12 at 21:03

5 Answers5

8

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"));
    }
}
Govinda Rajbhar
  • 2,926
  • 6
  • 37
  • 62
Amir Afghani
  • 37,814
  • 16
  • 84
  • 124
  • 1
    wow Thanks Amir, that is what I was looking for. I will now have a look through your code and and try and understand what's happening.. Thanks to Paul and Dave as well! :) –  May 12 '12 at 20:53
  • 1
    In general sense, this implementation is termed as the Simple Factory Pattern, to mean that it is no design pattern, but a OOP. I am going to give an answer with an example shortly as an answer. – maress May 12 '12 at 21:00
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

Paul Sullivan
  • 2,865
  • 2
  • 19
  • 25
  • hmmm.. why isn't "a man has been created a woman has been created" appearing on the screen when I run the test? Isn't my makePerson function calling for a male and female object to be created? –  May 12 '12 at 20:45
  • add a break point in your debugging environment to test (but it should) – Paul Sullivan May 12 '12 at 20:46
  • 1
    @user1073400 Because nothing calls `createPerson`. – Dave Newton May 12 '12 at 20:48
2

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();
    }
  }
Community
  • 1
  • 1
maress
  • 3,533
  • 1
  • 19
  • 37
  • Thank you very much for taking the time to provide me with this code example. It seems more complicated than mine but I will look at it as well and try to understand what's happening. I'm more familiar with programming and creating classes in C++ but not in Java.. –  May 12 '12 at 21:27
  • This would be the best example for factory method! – vins Jan 04 '17 at 23:08
  • The abstract method newStudent is really a factory method, make this example differs from the [simple factory pattern], which implemented using switch or if-else statement. – wangdq May 25 '17 at 13:29
1

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);
    }
}
JAN
  • 21,236
  • 66
  • 181
  • 318
0

Refactored the above code.

import java.util.HashMap;

class Person  {   
   String name;

   public Person(String name){
        this.name = name;
   }
   public void setName(String name){
        this.name = name;
   }
   public String getName(){
        return name; 
   }
}

class Male extends Person {   

    public Male(String name) {
        super(name);
        System.out.println("a man has been created with name:"+name);
    }
}

class Female extends Person{   

    public Female(String name) {
        super(name);
        System.out.print("a woman has been created with name:"+name);
    }
}

class PersonFactory {
     private static HashMap<String,Person> factory = new HashMap<String,Person>();
     static {
        factory.put("male", new Male ("Trump"));
        factory.put("female", new Female ("Theresa May"));

     }
     public static Person makePerson(String type) {                                        
         return factory.get(type);                     
     }
}


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

Key notes:

  1. Created the objects (Male and Female) once in static block.

  2. Not creating new object every time. Creation happens once. Every makePerson calls return existing object from the factory.

  3. Removed createPerson method

Have a look at related post @

Factory Pattern. When to use factory methods?

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211