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.
Related
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.
I have a simple Factory (GenericFudge) that creates objects of different types depending on external circumstances. Currently, my code looks something like this:
abstract class Fudge {
Fudge() {
}
void make() {
System.out.println("made.");
}
}
class VanillaFudge extends Fudge {
#Override
void make() {
System.out.print("Vanilla ");
super.make();
}
}
class ChocolateFudge extends Fudge {
#Override
void make() {
System.out.print("Chocolate ");
super.make();
}
}
class InvalidFlavorException extends Exception {};
// factory / proxy
public class GenericFudge {
Fudge mFudge = null;
GenericFudge(String flavor) throws InvalidFlavorException {
if (flavor.equals("Chocolate")) {
mFudge = new ChocolateFudge();
} else if (flavor.equals("Vanilla")) {
mFudge = new VanillaFudge();
}
}
void make() {
mFudge.make();
}
public static void main(String args[]) {
for (String flavor : new String[] {"Chocolate", "Vanilla"}) {
GenericFudge fudge;
try {
fudge = new GenericFudge(flavor);
fudge.make();
} catch (InvalidFlavorException e) {
System.out.println("Sorry, we don't make that flavor");
}
}
}
}
My goal is to get the details of chocolate and vanilla out of GenericFudge, so that when CaramelFudge is implemented, no changes to GenericFudge are required. For example, GenericFudge would iteratively call a "createIfItsMyFlavor()" method for every xxxFudge class. (In my actual application, I have to try them iteratively, but I'd be interested in other possibilities.)
My instinct was to use a static initializer per subclass (per xxxFudge) that adds "itself" to a list by calling a registerFudge method of GenericFudge, but this hits the chicken-and-egg problem (the class is never used, so its static initializer never gets invoked).
No doubt there's a better way I haven't envisioned. Thanks!
If you are using any kind of dependency injection system like Spring, this is easy to implement using #PostConstruct. If this works, then you can call a register method in GenericFudge from the method you annotate with PostConstruct. In GenericFudge, you have a map, and whenever addType is called you add it to the map. That way your GenericFudge remains unchanged, and new callers will register using PostConstruct. To simplify things further, you can define this in your base class Fudge, and pass the fudge name using the constructor, that way you don't have to declare the register method in each sub-class.
private String fudge;
public Fudge(final String fudge) {
this.fudge = fudge;
}
#Autowired
private GenericFudge fudge;
#PostConstruct
private void register() {
fudge.addType(fudge, this);
}
In GenericFudge
private Map<String, Fudge> fudgeTypes = Maps.newHashMap();
public void register(final String fudgeType, final Fudge fudgeInstance) {
fudgeTypes.put(fudgeType, fudgeInstance);
}
If you do not use any dependency injection system:
Another approach could be to have a static method in the base class Fudge, where you declare all the types of fudge and then return an instance based on the request. That way you don't modify the GenericFudge class, but only the base class of Fudge. This is not ideal, but it gets you away from having to modify the GenericFudge class, and instead of "registering" with something like PostConstruct, you put an entry into the Map.
Example (ImmutableMap from Guava, you can declare the map however you like , this is only for the example):
public abstract class Fudge {
private static final Map<String, Fudge> FUDGE_TYPES = ImmutableMap.of(
"Type1", new Type1Fudge(),
"Type2", new Type2Fudge()
// Add new entry when implemented
);
public static Fudge getFudge(final String fudge) {
if (FUDGE_TYPES.containsKey(fudge)) {
return FUDGE_TYPES.get(fudge);
} else {
// handle missing fudge depending on your preference
}
}
}
I have Foo.java, which is interface.
And lots of classes that implement it. Bar1.java , Bar2.java etc.
I have a method in frontend, that is like this: getBar(String bar)
I could just do it like this:
if(bar.equals("Bar1")) {
return new Bar1();
}
But can I somehow do it, that everytimes something new implements Foo.java , then I don't have to update my method, with new ELSE statement.
I thought like each implementation have unique ID or something, which I add to BarX.java , whenever I create it.
Any suggestions or thoughts? I thought maybe I can use enum or smthing or any other solution.
FYI: You realize, of course, that you should not write this:
if(bar == "Bar1") {
return new Bar1();
}
You should do it this way:
if("Bar1".equals(bar)) {
return new Bar1();
}
Looks like you need a factory (aka virtual constructor). If all your Foo implementers have a default constructor, you can do this:
public class FooFactory {
public static Foo create(Class<Foo> clazz) {
return clazz.newInstance();
}
public static Foo create(String className) {
return create(Class.forName(className));
}
}
There are exceptions to be handled; I don't have time to spell them out for you. You should see the idea. All you need to do is write a new class and your factory can handle it.
If there are other constructors, just elaborate the theme with parameters and additional calls. This should get you started.
Sounds to me like a job for dependency injection or reflection.
You can do :
Class myClass = Class.forName("my.namespace.MyClass");
That would be with reflection. Not very nice but doing the job.
You can create object by class name:
Class<?> clazz = Class.forName(className);
Object object = ctor.newInstance();
Or if you need call particular constructor (with one String argument strArgument for example):
Constructor<?> c = clazz.getConstructor(String.class);
Object object = c.newInstance(new Object[] { strArgument });
- Reflection is the way to go...
- But still you can use a method like this
public static Foo createObj(Class<Foo> clazz) {
return clazz.newInstance();
}
- And yes to mention, that it should be equals() and not ==
if(bar.equals("Bar1")) {
return new Bar1();
}
This is a classic factory pattern issue.
The solution is whenever you have to maintain a static Map and whenever you have a new "Bar" type you need to registed it in the map first, so whenever you want an object of that type, you can simply pick it from the map.
Consider the below classes
interface IVehicle {
public void drive();
public void stop();
}
class Car implements IVehicle {
public void drive(){
//logic goes here
}
public void stop(){
//logic goes here
}
}
class VehicleFactory{
public IVehicle createVehicle(String VehicleType){
IVehicle vehicle = null;
if("Car".equalsIgnoreCase(VehicleType) ){
vehicle = new Car();
}
if("Bus".equalsIgnoreCase(VehicleType) ){
//vehicle = new Bus();
}
if("Train".equalsIgnoreCase(VehicleType) ){
//vehicle = new Train();
}
return vehicle;
}
}
so whenever you have a new type of vehicle, you have to change the metho by adding the code for new Type of vehicle.
The solution is to improve the VehicleFactory class as below and all vehicle types should register in the map as shown below.
class Car implements IVehicle {
static{
VehicleFactoryFlexible.registerVehicle("Car", new Car());
}
public void drive(){
//logic goes here
}
public void stop(){
//logic goes here
}
public IVehicle createVehicle(){
return (IVehicle) new Car();
}
}
public class VehicleFactoryFlexible {
static Map vehicleRegistry = new HashMap();
public static void registerVehicle(String vehicleType, IVehicle veh){
vehicleRegistry.put(vehicleType, veh);
}
public IVehicle createVehicle(String vehicleType){
IVehicle vehicle = (IVehicle)vehicleRegistry.get(vehicleType);
return vehicle.createVehicle();
}
}
Using reflection you can scan a whole package for all of your BarX classes and work with this list instanciating if your input exists in the list. Or you could just use a Class.forName solution catching directly the error.
EDIT: check this out http://code.google.com/p/reflections/
Here's the sort of thing I'm trying to do:
class Foo {
private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects
//...
void process(int wIndex) {
process(things.get(wIndex);
}
private void process(WidgetA w) {
//Do things
}
private void process(WidgetB w) {
//Do other things
}
private void process(WidgetAB w) {
//Do completely different things
}
}
abstract class Widget {
//...
}
class WidgetA extends Widget {
//...
}
class WidgetB extends Widget {
}
class WidgetAB extends WidgetA {
}
Basically, a separate class gets an array index from user input, and passes it to the process(int) method, which is supposed to kick off a type-specific process() method to process the object at the passed index. The problem is that the objects are treated as Widget objects, not WidgetA, etc. I could loop through the types using instanceof, I guess, but I'm trying to avoid using that.
The logic in the process() methods needs to access private fields in the Foo class, so moving them to the Widget subclasses might not be the best idea.
So the question is, is there a way for the correct process() method to be called for a given Widget subtype, without using instanceof?
Yes, have a look at the Visitor pattern - also known as double dispatch.
Another potential solution is to use Java's reflection API's. Example:
class Foo {
private ArrayList<Widget> things; //Contains WidgetA, WidgetB and WidgetAB objects
//...
void process(int wIndex) {
Widget theWidget = things.get(wIndex);
try {
Class type = theWidget.getClass();
Class[] arg_types = new Class[]{type};
this.getMethod("process", arg_types).invoke(this, theWidget);
} catch (Exception e) {
//Could be SecurityException or NoSuchMethodException
}
}
private void process(WidgetA w) {
//Do things
}
private void process(WidgetB w) {
//Do other things
}
private void process(WidgetAB w) {
//Do completely different things
}
}
abstract class Widget {
//...
}
class WidgetA extends Widget {
//...
}
class WidgetB extends Widget {
}
class WidgetAB extends WidgetA {
}
The issue here being that you have to have defined a process() method for each type of object in the things list or an exception will be thrown at run-time. The compiler will not warn you if you are missing an implementation.
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.