Okay, so I'm starting to use Abstract classes, but I have a question : I have this abstract class Quest. My objective is to, when initializing a new Quest object, give it a random Quest type (Represented by a class extending Quest). For now my code is :
switch (r) {
case 0:
quest = new Bandit_Raids2();
break;
case 1:
quest = new Bandit_Raids();
break;
case 2:
quest = new Escort_Mission();
}
Is there any way to do this automatically, or just cleaner ?
I propose a different approach:
You could make your abstract class Quest an enum, and then implement the abstract methods in each enum constant (below is just an example):
public enum Quest {
ESCORT_MISSION {
public void start(){/* escort something */}
},
BANDIT_RAIDS{
public void start(){/* raid bandits */}
},
BANDIT_RAIDS2{
public void start(){/* raid bandits, again */}
};
public abstract void start();
// add here other methods and/or constructors and/or fields
}
That way you could then randomly select an enum constant (which is an instance of Quest):
Quest[] values = Quest.values();
int randomIndex = ThreadLocalRandom.current().nextInt(values.length);
Quest quest = values[randomIndex];
The only downside to this is that you have to put all the implementations into a single class file, which can get quite messy, quite easily
For the first part of the question, to do such thing in an automatic way will probably require reflexion but for the second part about being clean, most people will find it not that clean.
A possible solution if you agree to reduce a little the scope to "all classes that extends Quest" would be to have some static initializer method on all subclasses of Quest to register themself as a possible Quest and having a generic way to create instance for them
something like
public abstract class Quest {
private static final List<Supplier<Quest>> suppliers = new ArrayList<>();
protected static void register(Supplier<Quest> questSupplier) {
suppliers.add(questSupplier);
}
public static Quest createQuest(){
int r = 0; // replace by the random call you want there
return suppliers.get(r).get();
}
}
public class BanditQuest extends Quest{
static {
Quest.register(() -> new BanditQuest());
}
}
I would use the factory pattern.
public abstract class Quest {
// some generic code
}
public class BanditQuest extends Quest {
// some specific code
}
public interface Factory {
Quest create();
}
public class BanditFactory implements Factory {
#Override
public Quest create() {
return new BanditQuest();
}
}
List<Factory> factories = new ArrayList<Factory>();
factories.add(new BanditFactory());
// add all factories here
Quest quest = factories.get(r).create();
You need to make sure that r is not bigger than your list though.
Related
Firstly, I believe my question is badly worded but don't really understand how to phrase it.
I have a starting interface that is being implemented by a number of classes. What I want to do is to see if there is a way to create a new object such that I am being passed the generic interface, then based on the method .getClass().getSimpleName(), create a new object based on that string.
Is the only way to create a switch case statement? As the number of implementing classes are too many (about 100 or so).
Reference code:
public interface MyInterface {
public void someMethod();
}
then I would have my implementing classes:
public class MyClass1 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass2 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass3 implements MyInterface {
public void someMethod() { //statements }
}
What I want to have in the end is another class which is passed an argument of type MyInterface, get the simple name from that and create a new instance of MyClassX based on that simple name.
public class AnotherClass {
public void someMethod(MyInterface interface) {
if (interface == null) {
System.err.println("Invalid reference!");
System.exit(-1);
} else {
String interfaceName = interface.getClass().getSimpleName();
/**
* This is where my problem is!
*/
MyInterface newInterface = new <interfaceName> // where interfaceName would be MyClass1 or 2 or 3...
}
}
}
Any help is highly appreciated!
You can use reflection for this:
public void someMethod(MyInterface myInterface) {
Class<MyInterface> cl = myInterface.getClass();
MyInteface realImplementationObject = cl.newInstance(); // handle exceptions in try/catch block
}
This is a common problem with many solutions. When I face it, I never use reflection because it is difficult to maintain if it is part of a big project.
Typically this problem comes when you have to build an object based on a user selection. You can try a Decorator pattern for that. So, instead of building a different object for each option. You can build a single object adding functionality depending on a selection. For instance:
// you have
Pizza defaultPizza = new BoringPizza();
// user add some ingredients
Pizza commonPizza = new WithCheese(defaultPizza);
// more interesting pizza
Pizza myFavorite = new WithMushroom(commonPizza);
// and so on ...
// then, when the user checks the ingredients, he will see what he ordered:
pizza.ingredients();
// this should show cheese, mushroom, etc.
under the hood:
class WithMushroom implements Pizza {
private final Pizza decorated;
public WithMushroom(Pizza decorated) {
this.decorated = decorated;
}
#Override
public Lizt<String> ingredients() {
List<String> pizzaIngredients = this.decorated.ingredients();
// add the new ingredient
pizzaIngredients.add("Mushroom");
// return the ingredients with the new one
return pizzaIngredients;
}
}
The point is that you are not creating an object for each option. Instead, you create a single object with the required functionality. And each decorator encapsulates a single functionality.
For example, suppose I have a class
class Engine {
int horsepower;
...
}
and subclass
class EngineTurbo extends Engine {
Some turbineProperty;
...
}
on the other hand, I have a class (with some List return method)
class Plane {
Engine[] planeEngines;
...
public List<Engine> getListOfEngines() { ... }
}
and here is my question, having this subclass:
class PlaneTurbo extends Plane {
EngineTurbo[] planeEngines; // yes or no?
...
public PlaneTurbo(int quantity){
planeEngines = new EngineTurbo[quantity]; // yes? or...
super.planeEngines = new EngineTurbo[quantity];
}
public List<EngineTurbo> getListOfEngines() { ... } // best practices here
}
I'd like to know about best practices on the return List < SubClass > case.
I found some answers about using List < ? extends Engine > and something like that
Also found this terrific help (I share with all of you) but still I'm looking for best solution for this case
Thanks
Ah, BTW, after all of this I have another class (not subclass, or maybe yes), like...
class HangarOnlyTurboPlanes {
List<PlaneTurbo> turboPlanes; // only PlaneTurbo, not need Plane
...
public void someLogicInvolvingOnlyTurboPlanes(){
List<EngineTurbo> engines = turboPlanes.get(some).getListOfEngines();
...
}
}
If you are asking why, I'm working with "TURBO" app, but I like to keep it open to future another upperClass apps (maybe just Hangar) and/or siblingClass app (maybe SpaceEngineHangar whatever)
Thanks again
Your example is a candidate for generics. Where Plane will have reference not to concrete Engine but to a generics subclass of Engine that are specified by sub classes of Plane.
Change your Plane to be generic:
public class Plane<E extends Engine> {
E[] planeEngines;
public List<E> getListOfEngines() {return Arrays.asList(planeEngines);}
}
Then in your subclass all you have to do is specify concrete type of Engine and dont need to define a new variable to just hold EngineTurbo list:
public class PlaneTurbo extends Plane<EngineTurbo> {
public PlaneTurbo(int quantity) {
planeEngines = new EngineTurbo[quantity];
}
}
And finally your can get your EngineTurbo from PlaneTurbo without the need to define a new method that only returns EngineTurbo or some type of cast:
PlaneTurbo pt = new PlaneTurbo(5);
List<EngineTurbo> ets = pt.getListOfEngines();
I have an interface and its 2 implementations say :
public interface ObjectProcessor {
public void process(List<String> objectNames);
}
public CarImpl implements ObjectProcessor {
#override
public void process(List<String> carNames){
//car logic
} }
public VanImpl implements ObjectProcessor {
#override
public void process(List<String> vanNames){
//van logic
}
}
Now the caller who uses this interface looks like :
public void caller(VehicleType vehicleType, List<String> vehicleNames ) {
ObjectProcessor processor = null ;
if (VehicleType == VehicleType.CAR) {
processor = new CarImpl();
processor.process(vehicleNames);
}
}
VehicleType being an ENUM
This works fine. But is there anyway I can call an interface dynamically without
adding if statements. In the future if I am supporting another vehicle , I need to add an if statement along with a new implementation for the interface . How can I avoid this?
Overwrite abstract factory method in enum like this.
public enum VehicleType {
Car {
#Override
public ObjectProcessor createImpl() {
return new CarImpl();
}
},
Van {
#Override
public ObjectProcessor createImpl() {
return new VanImpl();
}
};
public abstract ObjectProcessor createImpl();
}
public void caller(VehicleType vehicleType, List<String> vehicleNames ) {
ObjectProcessor processor = vehicleType.createImpl();
processor.process(vehicleNames);
}
VechicleType combines enumeration with factory.
Or you can wirte all logics in enum like this.
public enum VehicleType {
Car {
#Override
public ObjectProcessor createImpl() {
return new ObjectProcessor() {
#Override
public void process(List<String> objectNames) {
// car logic
}
};
}
},
Van {
#Override
public ObjectProcessor createImpl() {
return new ObjectProcessor() {
#Override
public void process(List<String> objectNames) {
// van logic
}
};
}
};
public abstract ObjectProcessor createImpl();
}
In this case you don't need implementation classes (CarImpl, VanImpl, ...) any more.
Use Factory pattern. Here are some benefit from using it: http://javarevisited.blogspot.com/2011/12/factory-design-pattern-java-example.html#ixzz3ueUdV947
1) Factory method design pattern decouples the calling class from the target class, which result in less coupled and highly cohesive code?
2) Factory pattern in Java enables the subclasses to provide extended version of an object, because creating an object inside factory is more flexible than creating an object directly in the client. Since client is working on interface level any time you can enhance the implementation and return from Factory.
3) Another benefit of using Factory design pattern in Java is that it encourages consistency in Code since every time object is created using Factory rather than using different constructor at different client side.
4) Code written using Factory design pattern in Java is also easy to debug and troubleshoot because you have a centralized method for object creation and every client is getting object from same place
What you're basically implementing is a Factory pattern like proposed in the other answers. But in the end you will have to write an 'if' or 'switch' statement to select to correct implementation (or strategy) for your enum value. But like you mentioned yourself you'd have to extend this selection pattern whenever you add or remove an enum value. You can circumvent this by using a map like so:
public class ProcessorSelector {
private final Map<VehicleType, ObjectProcessor> processors;
public ProcessorSelector(Map<VehicleType, ObjectProcessor> processors) {
this.processors = processors;
}
public void process(VehicleType type, List<String> input) {
processors.get(type).process(input);
}
}
You can than configure your ProcessorSelector by passing a map with all the processor implementations mapped to the correct enum value (notice I used guava's ImmutableMap to conveniently construct the hashmap:
new ProcessorSelector(ImmutableMap.of(
VehicleType.CAR, new CarImpl(),
VehicleType.VAN, new VanImpl());
You'll never have to change your ProcessorSelector again, only the construction/configuration of the class. In fact you could say we just implemented the strategy pattern here. These selector classes are very common and if you feel you are implementing them quite often you could even use a more generic implementation, I recently described this in a blogpost: https://hansnuttin.wordpress.com/2015/12/03/functionselector/
I have an enum
public enum Vehicle {
CAR("CAR", "Car"), PUSHBIKE("PUSHBIKE", "PuschBike");
public boolean isCar()
{
...
}
public boolean isPushBike()
{
....
}
}
I have a 2 DAO CarDAO and PushBikeDAO which is are implementing a BaseDao
I have a JSF managed bean somthing like this
public class JsfManagedBean {
private Vehicle vehicle;
private BaseDAO baseDao;
public void Search()
{
//I need to get rid of this if statement
if (vehicle.isCar())
{
baseDao = new CarDao;
baseDao.search();
}
else if(vehicle.isPushBike())
{
baseDao = new PushBike;
baseDao.search();
}
//Please Note each type of search is very different call to an other party's Jar
}
}
I am trying to get rid of this if statement possibly by using generics or any proper OO technique
may be something like
baseDao = new baseDaoImpl<getClass(vehicle.getcode())>
where if vehicle.getcode() returns String value Car I do have a model class Car.
Just loud thinking (clinching the straws really :)).
This is an offshot of this question of mine
Add a method to the enum that calls new and returns the right dao.
Let each of the enum constants define their respective DAO classes:
public enum Vehicle {
CAR("CAR", "Car"){
public BaseDAO getNewDAO(){
return new CarDAO();
}
},
PUSHBIKE("PUSHBIKE", "PuschBike"){
public BaseDAO getNewDAO() {
return new PushBikeDAO();
}
};
Vehicle(String a, String b){/* ... */}
//this forces every enum constant to implement a getNewDAO() method:
abstract BaseDAO getNewDAO();
}
This way, you can use:
public void Search() {
baseDao = vehicle.getNewDAO();
baseDao.search();
}
Take a look at the Factory method pattern and the Strategy pattern if you'd like to know more. Enums are my preferred way to use the latter.
I would use a factory method, like so:
public class JsfManagedBean {
private static final Map<Vehicle,BaseDAO> daos;
static {
Map<Vehicle,BaseDAO> tmp = new HashMap<Vehicle,BaseDAO>();
tmp.put(Vehicle.CAR,new CarDAO());
tmp.put(Vehicle.BIKE,new BikeDAO());
daos = Collections.unmodifiableMap(tmp);
}
public static getDao(Vehicle v) {
return daos.get(v);
}
private Vehicle vehicle;
private BaseDAO baseDao;
public void Search()
{
baseDao = getDao(vehicle);
baseDao.search();
}
}
Unless you have more uses for DAO objects, you could make this code shorter:
if (vehicle.isCar()) new CarDao().search();
else if(vehicle.isPushBike()) new PushbikeDao().search();
With two alternatives, I'd stay with the if statement. If you had really many variants of vehicles, you could use a hash table keyed by the enum values and storing the DAO classes:
Map<Vehicle, Class> DAOClass = new HashMap<...>();
...
DAOClass.get(vehicle).getConstructor().newInstance().search();
Reflection is not that slow not to use here.
I have come across a bit of a problem. I have a class called "GameScreen" which will know what level and stage has been selected. From that I can build a string to suggest something like "level1_1" or "level1_2". The problem is how do I load this class now?
I was going to use Class.forname(string) however each level is a different class so how do I pass the new operator to the class?
I am trying to achieve something like this... world = new World(worldListener); where "World" is the class such as "level1_1".
Hope that makes sense.
Aside from the fact that there are much better ways to implement this (see the other answers, for example), this should work (not tested, ignores exceptions, may cause abdominal distention, etc.):
public World createWorld(String levelClassName, WorldListener listener) throws Exception
{
Class<?> clazz = Class.forName(name);
Constructor<World> ctor = (Constructor<World>) clazz.getConstructor(WorldListener.class);
World world = ctor.newInstance(listener);
return world;
}
You must use reflection (java.lang.reflect)
First, even if the class for each level is different, all of them should extend/implement a common superclass/interface so basic operations are available (v.g. a constructor, a startLevel() method, and so on).
With reflection, you can chose the class related to your level, instantiate it, and pass it to your engine so it invokes your class.
As a side note, I find the architecture strange. Unless there is some other reason to do this, I would suggest using a unique class for levels and loading the configuration for each level from files. It may not be suited if gameplay changes between level, though.
See the Factory Pattern. For your case you could implement a CreateLevel(String level) method which does a simple case-statement to determine which class to create or use reflection.
Um... there's 101 better ways of doing that.
Update For example:
public abstract class Level {
// or whatever your interface is
abstract public void createWorld(WorldListener worldListener);
abstract public void nextWorld();
}
public class Level1 extends Level {
public void createLevel(WorldListener worldListener) {
/** do it **/
}
public Level nextLevel() { return new Level2(); }
}
Then somewhere else:
Level cur = new Level1();
do {
cur.createLevel(worldListener);
...
cur = cur.nextLevel();
} while (cur != null);
Original
For example:
public abstract class Level {
final public int number;
public Level(int num) { this.number = num; levels[num-1] = this;/* set up level */ }
// adjust 10 to number of levels
static private Level[] = new Level[10];
static public getLevel(int num) { return levels[num-1]; }
// or whatever your interface is
abstract public void createWorld(WorldListener worldListener);
}
public class Level1 extends Level {
public Level1() { super(0); }
public void createWorld(WorldListener worldListener) {
/** do it **/
}
}
Then somewhere else:
Level.getLevel(1).createWorld();