Create subclass using parent's generic Builder - java

I am exploring using the Builder design pattern to create subclasses of a parent object, based specifically on the generic type of the subclass. That sentence is kind of confusing, here is what I mean:
public class Animal(){
private String name;
private String gender;
public Animal(Builder<?> builder){
this.name = builder.name;
this.gender = builder.gender;
}
public static Builder<T extends Animal>{
private String name;
private String gender;
public Builder<T> setName(String name){
this.name = name;
return this;
}
public Builder<T> setGender(String gender){
this.gender = gender;
return this;
}
public T build(Class<T> clazz){
try {
Constructor<T> c = clazz.getDeclaredConstructor(Builder.class);
c.setAccessible(true);
return c.newInstance(this);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
}
Except, this ends up being rather error prone and "hackish". I want to be able to have one Builder that creates all the subclasses.
Question
Is there a better way to do this? Maybe the Builder design pattern is just not suited for my needs. This works, but doesn't feel right.
NOTE: The true needs of this question are not as trivial as the Animal class example. You could imagine I am trying to build a subclass to a parent class that contains many arguments. Using the builder pattern will make this a much easier instantiation and easier to extend for future subclasses.
The subclassed objects will have their own methods ONLY. No extra fields, only methods strictly defined to their type of subclass.
I.e. a Duck is a subclass of bird and it quacks. An emu is a subclass of bird, but I don't want it to quack, it will only run. But I both want them to have a name and gender.

Rather than the user specifying the Animal class, I would have each Animal subclass have its own Builder which can build that Animal.
That is:
public abstract class Animal {
protected Animal(Builder<?> builder) { ... }
public abstract static class Builder<T extends Animal> {
// setters for fields common to all animals go here
public abstract T build();
}
}
public final class Dog extends Animal {
private Dog(Builder builder) {
super(builder);
}
public static final class Builder extends Animal.Builder<Dog> {
#Override
public Dog build() {
return new Dog(this);
}
}
}

Related

Java - How to choose what subclass to construct

I have a parent class:
public class Animal {
public Animal(String name, AnimalTypeEnum type) {
}
}
I have lots (in the case that has caused me to make this over 30) children:
public class Dog extends Animal {
public Dog(String name, AnimalTypeEnum type) {
super(name,type);
}
}
public class Cat extends Animal {
public Cat(String name, AnimalTypeEnum type) {
super(name,type);
}
}
The objects are constructed from many different places in the project (loaded on start up, created at various times in runtime. To "create" an object, I currently use this function (over 30 subclasses in the project, not just 2):
public static Animal create(String name, AnimalTypeEnum type) {
switch(type) {
case DOG:
return new Dog(name, type);
case CAT:
return new Cat(name, type);
}
}
It is important to note that none of the subclasses have any difference in parameters. The reason I'm using subclasses is because they have one or two functions that are overriden.
Say I now wanted to add a parameter for all subclasses, I'd need to:
Add the parameter to the Animal constructor
Add the parameter to the subclass constructors
Add the parameter to the create() function
(also change the parameter wherever the create() function is being called)
Ideally, I'd like to eliminate changing the subclass parameters (none of the subclasses have different parameters) and the create() function from the above process. But if that isn't possible, I'd like to find a better alternative to the create() function. The best solution I've thought of (psuedocode) is:
public Animal(String name, AnimalTypeEnum type) {
if (type == CAT) this.subclass(Cat);
if (type == DOG) this.subclass(Dog);
}
I think the above goes against the principle of class inheritance so I want to be clear that this isn't the solution I am trying to find, just how I imagine a solution could work.
This is a rather trivial issue but I feel that bad programming practices are behind it and I would like to rectify these. My questions would be (incase I haven't properly explained my problem/reasons):
Is inheritance even the ideal way to do this?
Is it possible to eliminate the process of changing the constructor in subclasses in this situation?
Is there anything I can do to remove the create() function, and assign the subclass when constructing Animal?
Thank you.
I think that you wonna use the Factory Pattern, so you have any options for solve your problem #Doleron showed the first one, but you can use this too:
public interface Animal {
public String getName();
}
The implementation Dog
public class Dog implements Animal{
private String name;
public Dog(String name) {
this.name=name;
}
#Override
public String getName() {
return name;
}
}
Cat
public class Cat implements Animal{
private String name;
public Cat(String name) {
this.name=name;
}
#Override
public String getName() {
return name;
}
}
Factory
public class AnimalFactory {
/*
* Some people use static attributs like:
* public static final String DOG ="DOG";
*/
public static Animal creatAnimal(String animal, String name){
if("DOG".equalsIgnoreCase(animal)){
return new Dog(name);
} else if("CAT".equalsIgnoreCase(animal)){
return new Cat(name);
}
return null;
}
}
Main
public static void main(String[] args) {
Animal animal = AnimalFactory.creatAnimal("dog", "pluto");
/*
* if you use static attribut you can call this form
*/
//Animal dog = AnimalFactory.creatAnimal(AnimalFactory.DOG, "pluto");
System.out.println("Name "+animal.getName()+ " class "+animal.getClass().getSimpleName() );
animal = AnimalFactory.creatAnimal("cat", "garfield");
System.out.println("Name "+animal.getName()+ " class "+animal.getClass().getSimpleName() );
}
you can see another example here.
Since you have an enum to identify the instance type, you could avoid the create/switch/if-else approach using a polymorphic enumeration like:
public enum AnimalTypeEnum {
CAT {
public Animal create(String name) {
return new Cat(name);
}
},
DOG {
public Animal create(String name) {
return new Dog(name);
}
},
COW {
public Animal create(String name) {
return new Cow(name);
}
};
abstract Animal create(String name);
}
As everything this approach has pros and cons. Please see if it fits to your requirements.
First of all, the base class Animal should be an abstract class, because you'll never give life to an Animal object but to a more specific type of Animal, i.e Dog, Cat et cetera. In this way, all animals will have some base methods already implemented.However, if some subclass needs to inherit from another class, you should consider Animal as an Interface, because Java doesn't allow multiple inheritance.
For your second question, if I correctly understand, why can't you add a protected member to the base class Animal and initialize it in the Animal costructor? Eventually, if subclasses as a specific value for this parameter, you can set it in the subclasses costructors.
Finally for the create() function in my opinion you should consider the Abstract Factory pattern.

Use Of polymorphism?

Employee Class
public class Employee {
protected String name;
protected String jobsheetnumber;
public Employee(String n,String j){
this.name = n;
this.jobsheetnumber = j;
}
public Employee(String name)
{
this.name = name;
}
public String getName() {
return name;
}
public String getJobsheetnumber() {
return jobsheetnumber;
}
public void setName(String name) {
this.name = name;
}
public void setJobsheetnumber(String jobsheetnumber) {
this.jobsheetnumber = jobsheetnumber;
}
}
Mechanic Class
public class Mechanic extends Employee{
public Mechanic(String name,String jobsheetnumber){
super(name,jobsheetnumber);
}
}
Supervisor Class
public class Supervisor extends Employee{
public Supervisor(String name){
super(name);
}
}
Company Class [snippet]
public class Company {
private String companyname;
private String companyaddress;
private String postalcode;
private String city;
private String country;
private String telephonenumber;
private String faxnumber;
private String province;
private Employee supervisor;
private Employee mechanic;
public Company(String companyname,String companyaddress,String postalcode,String city,String country,String telephonenumber,String faxnumber,String province,String supervisorname,String jobsheetnumber,String mechanicname)
{
this.companyname = companyname;
this.companyaddress=companyaddress;
this.postalcode = postalcode;
this.city=city;
this.country=country;
this.telephonenumber=telephonenumber;
this.faxnumber=faxnumber;
this.province=province;
supervisor = new Supervisor(supervisorname);
mechanic = new Mechanic(mechanicname,jobsheetnumber);
}
Employee Class is the superclass of both Mechanic and Supervisor class .. right now i am using the attributes of Employee i.e name and jobsheetnumber in the subclasses Mechanic and Supervisor Class
the code works fine .. but what if i want to add extended functionality in Mechanic and Supervisor ? then i cannot access those variables because the reference is to the Employee type object.
is this the correct use Of Polymorphism ? that we have to use super() as the constructor each time we create a reference of Supervisor/Mechanic Object ?
can we not use extended functionality inside Supervisor and Mechanic Class ?
If you want to call a superclass non-zero-arg constructor then yes, you have to call it explicitly. If the superclass constructor has no arguments then the call will be inserted for you.
The point of polymorphism is so that objects can take care of themselves without having to have the rest of the program micro-manage them, so the outside program refers to them by a reference with the type of an interface or superclass without having to know the exact concrete type. For instance all employees might have a work method, where that work takes a different form for a supervisor than it does for a mechanic; the work method would be overridden by the specific subclasses, and might call the specific methods on the subclasses. So the company can iterate through all the employees and call work on each of them, while work is defined differently for different subclasses of employee.
(In practice using subclasses to describe roles is too inflexible to work, since an employee could have multiple roles, or those roles can change over time. It's usually better to use composition, here assigning Role objects to an Employee.)
A better use of polymorphism would be the same interface (methods) for different implementations. So you can decide which implementation will be used in runtime.
To explain my point i will give a example using your classes.
public class Employee{
public void work(int hours){ doNothing();}
}
public class Supervisor extends Employee{
private Object pen;
private Object note;
#Override
public void work(int hours){
observations = superviseWorkers();
note.write(observations, pen);
}
}
public class Mechanic extends Employee{
private Tool tool;
private TaskBoard taskBoard;
#Override
public void work(int hours){
task = taskBoard.getPendent()
if(task.canSolveWithTool(tool))
{
solveTask(task, tool)
}
}
}
Using example:
employees = new List<Employee>();
employees.add(new Supervisor("foo"));
employees.add(new Mechanic("bar"));
foreach(employee in employees){
//you don't need to know which kind of employee you are treating here because you are only calling a behavior that all employees have.
employee.work(8);
}
If in many places in your code you are trying to figure out which object you are dealing with probably you are doing it wrong.
I used your classes in my examples to facilitate your understanding but as Nathan Hughes suggested in this case would be better to use composition instead of inheritance.
I will handle above scenario in two ways.
Solution 1: ( Interface as roles)
You can have "state" in Employee object and you can implement role as interface.
Employee will have all common attributes & methods. You can override base class method like doWork() in respective Employee implementations.
You can add specific behaviour of Mechanic, Supvervisor with use of interfaces.
public interface ISupervise{
public void doSupervise();
}
public class Supervisor extends Employee implements ISupervise{
public void doSupervise(){
}
}
public interface IMechanic{
public void doMechanicWork();
}
public class Mechanic extends Employee implements IMechanic{
public void doMechanicWork(){
}
}
Solution 2: (Decorate role)
Implement Decorator pattern for Employee to play multiple roles. Mechanic and Supervisor will decorate Employee behaviour. Refer to this example for better understanding of Decorator pattern.
Sample code can be found #
When to Use the Decorator Pattern?

Decide upon method usage at runtime. Polymorphism

Well, this is kind of embarrassing, but I've forgotten how to do the following in plain old Java:
abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
}
class Flea extends Animal {
private double jumpHeight;
public Flea(String name, double jumpHeight) {
super(name);
this.jumpHeight = jumpHeight;
}
public double jump() {
return jumpHeight();
}
}
class Giraffe extends Animal {
private int strideLength;
public Giraffe(int strideLength) {
super("Berta");
this.strideLength = strideLength;
}
public int stride() { return strideLength; }
}
class Gorilla extends Animal {
private String call;
public Gorilla(String call) {
super("Boris");
this.call = call;
}
public String call() { return "Gorilla says " + call; }
}
Now I would like to decide the appropriate method at runtime, without having to add all the methods to each Animal (no abstract methods) and without meaningless placeholders (like imagine a Flea has no call).
I would like to do this without casting. So no:
if(Animal instanceof Gorilla) ((Gorilla) animal).call();
I could come up with a solution incorporating interfaces like jumpable and could use that, but I'm sure there was a certain pattern that was exactly for this kind of task.
Any ideas?
You should consider the visitor pattern:
abstract class Animal {
public abstract void acceptAnimalVisitor(AnimalVisitor visitor);
}
class Flea extends Animal {
public void acceptAnimalVisitor(AnimalVisitor visitor){
visitor.visit(this);
}
}
// other animals also implementing acceptAnimalVisitor
public class AnimalVisitor{
public void visit(Flea flea){
// ...
}
// other visit methods for the other animals
}
However, this requires at least one method (the accept method itself). Also note that you can convert the AnimalVisitor into an interface, and that way you can easily achieve the so called double dispatch.

Using interface types in implementations vs public interfaces

Is there a point to using interface types in implementations, or should you only use them as part of the public interface of a class or interface?
Example (Java):
public class SomeClass {
// Declare list as..
private List<Object> list = new ArrayList<Object>();
// or...
private ArrayList<Object> list = new ArrayList<Object>();
// Does it matter which way list is declared if it's part
// of the private implementation?
// This parameter should be the most general interface type
// allowed because it's public-facing.
public void someMethod(List<Object> list) {
// ...
}
}
By defining them as abstract as possible, you're hiding implementation details. Should you ever wish to use a different subclass from List<T> instead of ArrayList<T>, then you can do so without breaking code everywhere.
Always make it as abstract as possible while still having the methods available that you need. That way your implementation is as flexible as possible.
For example, I am a person with a pet. Right now I have a cat, but what if I get on a vacation to Africa and happen to see a very awesome elephant? My cat will starve because nobody gave her food and I will put the elephant in my pocket back to Belgium. If I were to define it as a cat, I would have to change my entire class. Instead, I define it as an animal.
public class Person {
String name;
Animal pet;
// Getters & Setters + Constructor
}
public abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Cat extends Animal {
public Cat() { super("Cat")); }
}
public class Elephant extends Animal {
public Elephant() { super("Elephant")); }
}
public class Lion extends Animal {
public Lion() { super("Lion")); }
}
So when I make a new Person:
Person bestPersonInTheWorld = new Person();
bestPersonInTheWorld.setName("Jeroen");
bestPersonInTheWorld.setPet(new Cat());
I can simply kill the cat
bestPersonInTheWorld.dontFeedForTwoWeeks();
And I put my Elephant in the yard:
bestPersonInTheWorld.setPet(new Elephant());
Nothing has to be changed when it comes to implementation.

Creating an EnumMap with a generic type Enum

If I have a bunch of classes that all contain an Enum and EnumMap and I want to create a superclass for those classes.
public interface ColorEnum {
}
class ColorMarbles extends Toy {
enum MARBLE implements ColorEnum
{ BLUE, GREEN }
EnumMap<MARBLE, String> names = new EnumMap<MARBLE, String>(MARBLE.class);
//stuff
// fields
public void populate(ArrayList<String> designer) {
int i = 0;
for(MARBLE marble : MARBLE.values()) {
marble.name = designer.get(i);
i++;
}
}
}
class ColorBalloons extends Toy {
enum BALLOON implements ColorEnum
{ YELLOW, RED }
EnumMap<BALLOON, String> names = new EnumMap<BALLOON, String>(BALLOON.class);
//stuff
// fields
public void populate(ArrayList<String> designer) {
int i = 0;
for(BALLOON balloon : BALLOON.values()) {
balloon.name = designer.get(i);
i++;
}
}
}
How do I make create a superclass to have a generic EnumMap that contains an enum of type ColorEnum like this?
public abstract class Toy {
EnumMap<ColorEnum, String> names;
}
eidt: I realize that I was too vague with my example. Dogs are probably a bad example. I change it to something hopefully more clear.
What I have is a bunch of classes with methods like populate which populates the EnumMap. The names are in a predefined order. Instead of defining populate in every class, I'm hoping to be able to bring it to the Toy superclass so I don't have to keep copy-pasting in each new class type Toy.
Hopefully this will explain more what I'm looking for.
I have a feeling your design is needlessly overcomplicated.
With enums
If you don't require a class inheritance, you can work with enums directly as with top level classes.
public interface Animal {}
public enum Dog implements Animal {
HUSKY("Husky"), LAB("Labrador");
private final String name;
Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Enums can declare fields, methods and implement interfaces like any other Java classes. Their only limitation is that their direct superclass is always java.lang.Enum and they can't be extended.
However every enum constant can have its own set of unique data passed to its constructor. It is even possible that each of the constants can override a common method of that enum with its unique implementation.
A nice tutorial explaining more about the full power of enums:
http://javarevisited.blogspot.cz/2011/08/enum-in-java-example-tutorial.html
Without enums
In case you need an actual class inheritance for sharing some common methods (for example from the Animal superclass), I still would drop the map approach and rather try something more OOP oriented:
public class Animal {
}
public abstract class Dog extends Animal {
public abstract String getName();
public static class Husky extends Dog {
#Override
public String getName() {
return "husky";
}
}
public static class Lab extends Dog {
#Override
public String getName() {
return "labrador";
}
}
}
One mechanism I have used for something like this is to extend a generic base class that has a generic parameter that allows you to pass the Enum details up to it.
This example defines a base Table class for database tables:
public class Table<Column extends Enum<? extends Column>> {
// Name of the table.
protected final String tableName;
// All of the columns in the table. This is actually an EnumSet so very efficient.
protected final Set<Column> columns;
/**
* The base interface for all Column enums.
*/
public interface Columns {
// What type does it have in the database?
public Type getType();
}
// Small list of database types.
public enum Type {
String, Number, Date;
}
public Table(String tableName,
Set<Column> columns) {
this.tableName = tableName;
this.columns = columns;
}
}
Now you can subclass this:
public class VersionTable extends Table<VersionTable.Column> {
public enum Column implements Table.Columns {
Version(Table.Type.String),
ReleaseDate(Table.Type.Date);
// Sadly all of this must be in ALL of your enums but most of the work can be pushed up to `Table`
final Table.Type type;
Column(Table.Type type) {
this.type = type;
}
#Override
public Type getType() {
return type;
}
}
public VersionTable() {
super("Versions", EnumSet.allOf(Column.class));
}
}
and make use of functionality in the parent class that handles your enum.
Note here I am passing an EnumSet to the Table constructor. I am sure you could change this to accommodate your EnumMap requirement if you decide an EnumSet is insufficient.

Categories

Resources