How can I avoid this if statement - java

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.

Related

How to implement factory pattern with dagger using annotation

What I have done currently is
Created an abstract class
public interface AbstractRawPathStrategy {
String getRouteKey();
void processRequest();
}
Implemented the classes
public class GetDocumentImpl implements AbstractRawPathStrategy {
#Override
public String getRouteKey() {
return "GET_DOCUMENT";
}
#Override
public void processRequest() {
log.info("Inside get document");
}
}
Created a routing factory
public class RawPathStrategyFactory {
private final Map<String, AbstractRawPathStrategy> dictionary;
#Inject
public RawPathStrategyFactory(final Set<AbstractRawPathStrategy> abstractRawPathStrategySet) {
dictionary = new HashMap<>();
for (AbstractRawPathStrategy abstractRawPathStrategy : abstractRawPathStrategySet) {
dictionary.put(abstractRawPathStrategy.getRouteKey(), abstractRawPathStrategy);
}
}
public AbstractRawPathStrategy getByRouteKey(final String rawPath) {
return dictionary.get(rawPath);
}
}
Instantiated the factory
#Module
public class AppModule {
#Provides
#Singleton
public RawPathStrategyFactory getRouteKeyStrategyFactory() {
Set<AbstractRawPathStrategy> abstractRouteKeyStrategies = new HashSet<>();
abstractRouteKeyStrategies.add(new GetDocumentImpl());
abstractRouteKeyStrategies.add(new GetUserRightsImpl());
return new RawPathStrategyFactory(abstractRouteKeyStrategies);
}
What I want is to go to respective class based on the route key (String). How can this be done without instantiating each class with new in AppModule. Any cleaner way to do this?
Try to use multibindings when create RawPathStrategyFactory
https://dagger.dev/dev-guide/multibindings.html
The easy, boring, way would be to use some static identifier which you'll have to set for each distinct subtype of your abstract class, and subsequent subtype thereof.
The more complicated, albeit fun, way to do this would be to use reflection.

How to create a new object based on interface implementation

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.

Can I have a single instance of Interface

In my Android application I have a class which gives me static string values; something like this:
public class VehicleInfo {
public static String getVehicleEnginePower(boolean isNew) {
return isNew ? "1800CC" : "1600CC";
}
}
Now I have another category, so I will have to pass another Boolean, and I will get the value I need. However, these categories will keep on increasing. So I looked into the Open/Closed principle which looks promising for quick enhancement. To ensure this I will make the VehicleInfo class as an Interface and then I will have other classes implement VehicleInfo.
public interface VehicleInfo {
String getVehicleEnginePower();
}
public class NewVehicle implements VehicleInfo {
#Override
public String getVehicleEnginePower() {
return "1800CC";
}
}
and the other category classes will also be something like this. In this way I will have to add another class for all the new categories.
The question I wanted to ask is: is there a way that I can have single instance of this interface? Because in the whole application flow, a user will only be able to see one category until he switches to another category.
I don't want to instantiate these classes at multiple points. To clarify my question, I want to do something like this at the start of my application:
if (isNew) {
VehicleInfo vehicleInfor = new NewVehicle();
}
And in the whole application, whenever I call VehicleInfo.getVehicleEnginePower, it should always return engine power from the NewVehicle class.
Is something like this possible? Or am I just being silly and I will have to instantiate this interface on multiple points?
Maybe you need a singleton here
public class VehicleInfoManager {
private static VehicleInfoManager INSTANCE = new VehicleInfoManager();
private VehicleInfo currentVehicleInfo;
public static VehicleInfoManager getInstance() {
return INSTANCE;
}
public void setCurrentVehicleInfo(VehicleInfo info) {
this.currentVehicleInfo = info;
}
public String getVehicleEnginePower() {
return this.currentVehicleInfo.getVehicleEnginePower();
}
private VehicleInfoManager() {
// Constructor private by default
}
}
Then you can call it from everywhere like this
VehicleInfoManager.getInstance().getVehicleEnginePower()
//Or set current info like this
VehicleInfoManager.getInstance().setCurrentVehicleInfo(new NewVehicle())
Just be careful as currentVehicleInfo is null by default so you need to handle null pointer cases.
If I understand your question correctly.
My solution to this would be Enum
public enum VehicleEnginePower {
NEW ("1800CC"),
OLD ("1600CC"),
private final String name;
private Modes(String s) {
name = s;
}
public String toString() {
return this.name;
}
}
Then you can do
if (isNew) {
String powerOfEngine = VehicleEnginePower.NEW.toString();
}

How to get Child class?

I want to create an object of child class
more than 100 class extend MasterClass
MasterClass is
public class MasterClass{
int key;
String value;
String displayValue;
boolean status;
}
public class User extends MasterClass{
public User(){ }
}
public class Customer extends MasterClass{
String productName;
public Customer (){ }
}
etc...
i will get a MasterClass object from client, i wanted to type cast that object to respective one
if(masterClass instanceof User) {
User a_user = (User) a_ masterClass;
…
} else if(masterClass instanceof Customer) {
Customer a_customer = (Customer) a_ masterClass;
…
}
if i do this i will end up with 100s of else if.
Please let me know how i can achieve this without else if?
Thanks in advance.
Use polymorphism and generics, as Java intended.
Polymorphism lets you call a method on your object that behaves differently for every type. The easiest way to achieve this is to provide an abstract method in the base class MasterClass and then override it with different functionality in every extended class. You are probably looking for something like this:
class MasterClass {
int age;
// ...
public abstract void doWork();
public int getAge() { return age; }
// .. more methods
}
class User extends MasterClass {
// customize User here
#Override
public void doWork() { /* User does work in some way */ }
}
class Customer extends MasterClass {
// customize Customer here
#Override
public void doWork() { /* Customer does work in some other way */ }
}
// ...
If you are not too familiar with OOP, here is a good introductory tutorial.
If you are not allowed to alter your classes, you can populate a look-up table like HashMap<Class, MyFunctor> where you can assign a different functor for every type of person you have.
Also, you might want to use generics. Generics allow you to capture and restrict the type of objects passed to your methods.
Maybe you can use generics with the constraint T extends MasterClass?
Using basic concepts of Design Pattern you can create a constructor like this in the object where you try to initialize
MasterClass masterClass;
public MyCreatorOject(MasterClass masterClass)
{
this.masterClass = masterClass;
}
later when you create the object it can be
new MyCreatorObject(new User());
or
new MyCreatorObject(new Customer());

Getting one implementation of Foo.java

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/

Categories

Resources