Reputation: 51
Let's say I have a class named Human
in ProjectA
. It is instantiated in the CreatureBuilder
class of the same project.
Now I want to create a new class called Cyborg
in a different project, i.e. in ProjectB
. ProjectB
has ProjectA
in its imports, but ProjectA
knows nothing about ProjectB
.
Cyborg extends Human
, and must also be instantiated by CreatureBuilder
of ProjectA
(so, Cyborg
is located in ProjectB
, I call CreatureBuilder
from ProjectB
to instantiate Cyborg
, but CreatureBuilder
is located in ProjectA
, as well as my Human
class).
I need a logic to create a Human
when CreatureBuilder
is instantiated from ProjectA
, and to create a Cyborg
when CreatureBuilder
is instantiated from ProjectB
.
I think it is achievable by creating an interface with a getCreature()
method in ProjectA
. This method will be overridden in ProjectB
to return new Cyborg
and then passed back to CreatureBuilder
of ProjectA
.
Any other suggestions? What do you think is the best workaround? Can I use reflection API instead?
Cheers!
Upvotes: 3
Views: 240
Reputation: 4091
CreatureBuilder
can delegate the creature's creation to the caller by asking for a Supplier.
public class CreatureBuilder {
public Creature getCreature(Supplier<Creature> creatureSupplier)
{
//do some unknown things
return creatureSupplier.get();
}
}
Usage from ProjectA
public class ProjectA {
public static void main(String[] args) {
Creature A = new CreatureBuilder().getCreature(Human::new);
}
}
Usage from ProjectB
public class ProjectB {
public static void main(String[] args) {
Creature B = new CreatureBuilder().getCreature(Cyborg::new);
}
}
And never use reflection if you're not forced to.
If you're sticked with Java 7, the principle remains the same except that it's a bit more verbose.
You have to declare and use your own Supplier-like interface
public interface CreatureSupplier {
Creature get();
}
public class CreatureBuilder {
public Creature getCreature(CreatureSupplier creatureSupplier)
{
//do some things
return creatureSupplier.get();
}
}
Usage is a bit more verbose
public class ProjectA {
public static void main(String[] args) {
Creature A = new CreatureBuilder().getCreature(new CreatureSupplier() {
@Override
public Creature get() {
return new Human();
}
});
}
}
public class ProjectB {
public static void main(String[] args) {
Creature B = new CreatureBuilder().getCreature(new CreatureSupplier() {
@Override
public Creature get() {
return new Cyborg();
}
});
}
}
And... that's it, you've got the same behaviour as the one in Java 8.
Upvotes: 5
Reputation: 14228
I think you are looking at factory pattern. Yes you can do it with an interface and a factory class in project A and a factory class in B that extends it.
Example:
In Project A:
public interface CreatureBuilder
{
Creature getCreature(String type);
}
public class Creature
{
//fields of Creature class
}
public class Human extends Creature
{
//fields of Human
}
public class Ape extends Creature
{
//fields of Ape
}
public class ProjectAFactory implements CreatureBuilder
{
@Override
public Creature getCreature( String type )
{
switch(type)
{
case("Human"): return new Human();
case("Ape") : return new Ape();
default : return null;
}
}
}
You can call ProjectAFactory.getCreature("Human");
to create Human object
Then in project B
public class ProjectBFactory extends ProjectAFactory
{
@Override
public Creature getCreature(String type)
{
switch(type)
{
case ( "Cyborg" ) : return new Cyborg();
default : return super.getCreature(type);
}
}
}
public class Cyborg extends Creature
{
//fields related to Cyborg which also fields of Creature in project A
}
You can call ProjectBFactory.getCreature("Cyborg");
to create Cyborg or even ProjectBFactory.getCreature("Human")
to get a Human Object.
Upvotes: 1