Sahand
Sahand

Reputation: 8370

Java Factory pattern - How to prevent anonymous subclasses

I'm doing a school assignment where I have to implement the Factory pattern. I have come a long way, but there is one last thing I have not been able to get working.

I have the following classes:

//Human.java
package human;
public abstract class Human{
    public static Human create(String namn, String pnr){
        char nastsist_char = pnr.charAt(9); // takes second last char in pnr
        String nastsist_string = Character.toString(nastsist_char);
        float siffra = Float.parseFloat(nastsist_string);   //Converts to float
        if ((siffra % 2) == 0){                 //Checks if even
            return new Woman(namn, pnr);            
        }
        else{
            return new Man(namn, pnr);
        }

    }

}

//Man.java
package human;
class Man extends Human{
    private final String pnr;
    private final String namn;

    protected Man(String n, String p){
        namn = n;
        pnr = p;
    }
    public String toString(){
        return "My name is "+namn+" and I am a man.";
    }   
}

//Woman.java
package human;
class Woman extends Human{
    private final String pnr;
    private final String namn;

    protected Woman(String n, String p){
        namn = n;
        pnr = p;
    }
    public String toString(){
        return "My name is "+namn+" and I am a woman.";
    }

}

I also have a class called Test.java. Here comes my problem: In Test.java, I want to make it impossible to do the following:

Human h = new Human(){};

i.e., to create an anonymous subclass of Human. Unfortunately, this line of code runs just fine, and an anonymous subclass is created. How can I make this line of code unexecutable/uncompilable?

PS. I have already tried making Human final. It was not allowed to combine final with abstract in a class.

EDIT:

So I got the tip to make the Human constructor protected. Here's what it looks like after the change:

//Human.java
package human;
public abstract class Human{
    protected Human(){}

    public static Human create(String name, String idNumber){
        char secondlast_char = idNumber.charAt(9); // takes second last char in pnr
        String secondlast_string = Character.toString(secondlast_char);
        float siffra = Float.parseFloat(secondlast_string); //Converts to float
        if ((siffra % 2) == 0){                 //Checks if even
            return new Woman(name, idNumber);           
        }
        else{
            return new Man(name, idNumber);
        }
    }
}

Unfortunately, I still do not get an error neither when running or compiling the code of Test.java, which by the way looks like this:

import human.*;
public class Test{
    public static void main(String[] args){
        Human h = new Human(){};
    }
}

Upvotes: 1

Views: 727

Answers (3)

Fritz Duchardt
Fritz Duchardt

Reputation: 11920

Please note that making it impossible to create anonymous classes from your base class is not the main problem with your implementation of the Factory Pattern. The pattern's intention is to encapsulate object creation logic, so that it can be changed easily without affecting the classes that are being instantiated nor the clients that use those instances.

Putting a static factory method into a base class that creates concrete instances of its sub classes defeats the objective of class separation thanks to inheritance as well as the purpose of the factory pattern.

I would seriously consider sticking your factory method into a separate class, e.g. HumanFactoryImpl and provide a corresponding interface.

Upvotes: 0

panagdu
panagdu

Reputation: 2133

Use the default modifier for constructors:

Human(){}

Upvotes: 0

Boris the Spider
Boris the Spider

Reputation: 61168

Add a constructor with the default visibility:

public abstract class Human {        
    Human(){}    
}

By default this only allows access to classes within the same package so it is known as "package private".

Upvotes: 2

Related Questions