Java Factory pattern - How to prevent anonymous subclasses - java

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(){};
}
}

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".

Use the default modifier for constructors:
Human(){}

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.

Related

How to return an object from different classes in Java?

I'm beginner in Java and I need help. I have several classes.
public class A{
private String name = "A";
public String getClassName(){
return "A";
}
public void editClassName(String name){
this.name = name;
}
}
public class B{
private String name = "B";
private int counter = 0;
public String showClassName(){
return "B";
}
public int getCount(){
return counter;
}
}
Such classes could be more. I also need to have some class witch can return an instance of asked class.
public class ClassSelector{
public static ??? getClassByName(String nameOfClass){
if(nameOfClass == "A"){ return new A();}
if(nameOfClass == "B"){ return new B();}
}
}
And here is a code that I want to use to get access to appropriate class:
ClassSelector.getClassByName("A").getClassName();
ClassSelector.getClassByName("B").showClassName();
I need to have an access to the instance of the class, and each instance can show it's unit methods that class has.
In this situation I don't get which return type I should use in the 'getClassByName' method.
I will very appreciate for help.
I would very much like to offer an alternative architecture if possible! It's not much different to what you have.
Firstly, we'll define some interface.
public interface Named {
String getName();
}
Now, this means you can have lots of concrete classes but provided they implement this interface, you'll know (and the Java compiler will know) that they have the getName method available to you.
Next, let's update your class to implement this interface.
public class A implements Named {
public String getName() {
return "A";
}
}
You could do this for classes B, C... and so on.
Now your method return type can be set to Named, that is:
public class ClassSelector{
public static Named getClassByName(String nameOfClass){
if(nameOfClass.equals("A")){ return new A();}
if(nameOfClass.equals("B")){ return new B();}
}
}
And you can access the response like so:
Named response = ClassSelector.getClassByName("A").getName();
As Eran suggested, it can be only of type Object, because they don't have a common superclass other than Object. If you don't want to work with Object class, you can create a body-less interface and implement it in both(or multiple classes) and that can be your return type.
After the call of the method, you can find the specific type of the returned object with instanceof;
What you are trying to do is called the Factory Pattern.
Assuming you are crating Widgets I suggest;
Introduce a Widget interface and have A and B implement Widget as per Christopher’s answer
Rename ClassSelector to WidgetFactory
Rename the method getClassByName to create, make it non-static and return Widget instances
This is more aligned with common Java name conventions and thus makes your code readily understandable by most developers.
If you want to keep your factory static it is of course possible but it may make your code less testable as it cannot be switched out for another factory in your tests. This is problematic if A and B are heavy weight objects that carries a lot of external dependencies that you may want to exclude.
If testability is a concern you may even consider making the factory implement a WidgetFactory interface...
First of all, please note that for string comparison you have not to use "==" (the problem is in nameOfClass == "A" and so on, I say it only for completeness).
I want suggest a solution based on reflection, that maybe could be more concise:
public interface IClass {
}
public class A implements IClass {
private String name = "A";
}
public class B implements IClass {
private String name = "B";
}
public class ClassSelector {
public static void main(String[] args) {
IClass obj = null;
try {
Class c = Class.forName("A");
obj = (IClass) c.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("Create object of type " + obj.getClass());
}
}
Thanks to all guys, who have answered my. Forgive me, when I create the first post, I made one mistake, which leads to misunderstanding what I mean. Now the code in the first post is better to show what I'm looking for.

If Downcasting Should Be Avoided, What Should I Do?

have the following interface class:
public interface IGameObject {
String gameObjectID();
String gameObjectName();
void isActionValid(String action);
void viewActions();
}
I have the following abstract class that implements the above interface.
package gameprobjectpackage;
public abstract class Weapon implements IGameObject {
//Left out getters/setters to keep it simple
private String gameOjectID;
private String gameObjectName;
private int damage;
public Weapon(String gameOjectID, String gameObjectName,int damage) {
super();
this.gameOjectID = gameOjectID;
this.gameObjectName = gameObjectName;
this.damage = damage;
}
I've come across a few posts that suggest downcasting should be avoided. I understand why, BUT, my question is what do I do if I need to access a method that is specific to a sub class. For example:
public class ChargeGun extends Weapon {
private String [] chargeGunActions;
public ChargeGun(String gameOjectID, String gameObjectName, int damage) {
super(gameOjectID, gameObjectName, damage);
chargeGunActions = new String [3];
chargeGunActions[0] = "Charge and Fire";
chargeGunActions[1] = "Release";
chargeGunActions[2] = "Drop Gun";
}
//This method is only meant for gun, and this type of gun is the only one in my game.
//This method, I don't belive should be in the abstract method weapon, because NOT every weapon is a gun.
public void reloadGun()
{
}
I store in in an interventory hashmap like so:
Map<String,IGameObject> inventory = new HashMap<String,IGameObject>();
When I retrieve it, I will get an IGameObject, how do I properly cast it, so that I can access the method in ChargeGun?
You can use the visitor pattern which frees you from casting. The idea is simple : You have an inventory of IGameObject which would have a method accept(GameObjectVisitor v) which directly calls v.visit(this). In your GameObjectVisitor, you just have to implement visit methods for each implementations : For example visit(Chargegun g), visit(Sword s), etc...
To explain it another way, it's like the principle of a boomerang : The GameObjectVisitor calls item.accept(this), and the Item implement accept(GameObjectVisitor g) with a simple g.visit(this).
By doing this, the Visitor has multiple visit methods for each implementation and can do specific stuffs without having to cast/using instanceof.

Java: Classes do not find each other in package (factory design pattern)

I have three different classes:
Woman.java
package human;
public class Woman extends Human{
private final String pnr;
private final String namn;
public Woman(String n, String p){
namn = n;
pnr = p;
}
public String toString(){
return "My name is "+namn+" and I am a woman.";
}
}
Man.java
package human;
public class Man extends Human{
private final String pnr;
private final String namn;
public Man(String n, String p){
namn = n;
pnr = p;
}
public String toString(){
return "My name is "+namn+" and I am a man.";
}
}
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 Man(namn, pnr);
}
else{
return new Woman(namn, pnr);
}
}
}
When I try to compile the file Human.java, I get the error
cannot find symbol: class Man,
and
cannot find symbol: class Woman.
When I try to compile the file Man.java or Woman.java, I get the error
cannot find symbol: class Human.
No changing of public/private visibility of the classes have helped. All the files are located in a directory called human.
What is the problem here?
I should add that the goal I'm trying to achieve is to have an abstract class Human that can not be instantiated, and in that class I want to have a create method that returns instances of either Man or Woman depending on pnr. Also, I do not want Man or Woman to be possible to instantiate in any other way than through the create method.
Thanks
There's no problem with your code or packaging, so the problem is elsewhere. How do you compile? I'm guessing you might be doing
javac human/Human.java
which will not work, since Man and Woman is then not on the classpath and thus not known to the Java compiler when working on Human. You should include these when compiling:
javac human/*.java
Cheers,
Do you compile them by yourself, in a terminal or something?
Try to compile all files all together then:
javac Man.java Woman.java Human.java
You have cycles in the classes. So you have two choices.
1) Compile all together
2) Create a new class e.g. Factory and instantiate the objects there
It's never a good idea to create cycles in you code
Have you tried : javac *.java in your folder ?
Java: How can I compile an entire directory structure of code ?

Inheritance, deriving from a derived class

I am trying to create a class from a class that is already derived from another class. (bit confusing) It adds one extra attribute in the newest "PricedApt" class that is "price". The desired constructor call is as follows
PricedApt p = new PricedApt("jill", 900, true, "jack", 1050.00);
The class is missing its constructor and im trying to create it but not sure whats wrong.
This is the (already derived (2nd) class)
public class RentalApt extends Apartment{
private String tenant;
private boolean rented;
public RentalApt(String owner, int size, boolean rented, String who){
super(owner,size);
tenant = who;
this.rented = rented;
}
My code for the (3rd) class that I have attempted is
public class PricedApt extends RentalApt {
private double price;
public PricedApt(String owner, int size, boolean rented, String who, double priceTag) {
super(owner,size,who);
price = priceTag;
}
}
Can anyone point me in the right direction as to what I am doing incorrectly? The compilation error I'm receiving is cannot find symbol (line 2 column 3).
For one, RentalApt has a four-argument constructor, but its subclass PricedApt is calling super() with only three arguments.
Try changing
super(owner,size,who);
to:
super(owner,size,rented,who);

Regarding alternative to interfaces and acessing with static imorts

I was going through a research in which I dont want to store the constants in the interface itself, so I was looking for alternatives like enums but another approach I have found is that ....t instead of using an interface, use a final class with a private constructor. (Making it impossible to instantiate or subclass the class, sending a strong message that it doesn't contain non-static functionality/data. and we can also take the advantage of static import in that case
Public final class KittenConstants
{
private KittenConstants() {}
public static final String KITTEN_SOUND = "meow";
public static final double KITTEN_CUTENESS_FACTOR = 1;
}
two independent things. 1: use static imports instead of abusing inheritance. 2: If you must have a constants repository, make it a final class instead of an interface . Please advise is this approach is correct..!!
To avoid some pitfalls of the constant interface (because you can't prevent people from implementing it), a proper class with a private constructor should be preferred (example borrowed from Wikipedia):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
And to access the constants without having to fully qualify them (i.e. without having to prefix them with the class name), use a static import (since Java 5):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
Please show how we can do same ting with enum also..!
You can achieve your "constants" via an enum:
public enum Animal {
Kitten("meow", 1),
Puppy("woof", 2);
private final String sound;
private final double cuteness;
Animal (String sound, double cuteness) {
this.sound = sound;
this.cuteness = cuteness;
}
public String getSound() {
return sound;
}
public double getCuteness() {
return cuteness;
}
}
To use:
String sound = Animal.Kitten.getSound();
double cuteness = Animal.Kitten.getCuteness();
The simple answer is that you can't do that with an enum. An enum defines a set of related constants with the same type.
What you have in the KittenConstants case is a set of constants with fundamentally different types. This doesn't fit the enum model. (If you change the problem a bit; e.g. by generalizing over different kinds of SFA, you can make it fit ... as #Bohemian does ... but if that's not what you are trying to achieve, enum is not the right solution.)
What you have in the Constants case is a bunch of named floating point constants that you want to use as values. (All the same type ... which helps!) Now you could declare them as an enum as follows:
public enum Constants {
PLANCK_CONSTANT(6.62606896e-34),
PI(3.14.59);
public final double value;
Constants(double value) {this.value = value);
}
The snag is that you need to use ".value" to access each named constant's numeric value; e.g.
import static Constants.*;
....
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT.value / (2 * PI.value);
}
.... which is kind of ugly, and I don't think there is any way around the ugliness.
Bottom line - enums are not an ideal replacement for all kinds of constant.

Categories

Resources