I have below set of interfaces and classes.
Note the doSomething method. It has to check for the instance of the object before calling the interface method on it. I would like to avoid that, as it involves changing this method whenever a new Vehicle is added. What is the best way of doing this in Spring?
class SomeService {
#Autowired
VehicleRepairService<Car> carRepariService;
#Autowired
VehicleRepairService<Truck> truckRepairService;
public void doSomething(String vehicleId) {
Vehicle vehicle = getVehicle(vehicleId);
if(vehicle instanceof Car) {
carRepairService.repair(vehicle);
} else {
truckRepairService.repair(vehicle);
}
}
}
interface VehicleRepairService<T extends Vehicle> {
void repair(T vehicle);
}
class CarRepairService implements VehicleRepairService<Car> {
#Autowired
SomeDependency some;
void repair(Car vehicle) {
.......
}
}
class TruckRepairService implements VehicleRepairService<Car> {
#Autowired
DifferentDependency different;
void repair(Truck vehicle) {
.......
}
}
Since none of the answers has a generic solution. Spring allows to inject all implementations of a type. The solution below is not tested I wrote it in a text editor. It can be improved by making VehicleRepairService an abstract class and use for example ResolvableType retrieve the generic type in this abstract class. Than it is not necessary anymore to implement the getType method in every instance.
class SomeService {
#Autowired
private List<VehicleRepairService> vehicleRepairServices;
public void doSomething(String vehicleId) {
Vehicle vehicle = getVehicle(vehicleId);
for(VehicleRepairService vehicleRepairService:vehicleRepairServices){
if(vehicle.getClass().equals(vehicleRepairService.getType())){
vehicleRepairService.repair(vehicle);
}
}
}
public Vehicle getVehicle(String id){
return new Truck();
}
}
interface VehicleRepairService<T extends Vehicle> {
void repair(T vehicle);
Class<T> getType();
}
class CarRepairService implements VehicleRepairService<Car> {
public void repair(Car vehicle) {
}
#Override
public Class<Car> getType() {
return Car.class;
}
}
class TruckRepairService implements VehicleRepairService<Truck> {
public void repair(Truck vehicle) {
}
#Override
public Class<Truck> getType() {
return Truck.class;
}
}
In general where you have instanceof together with switch or if .. else if ..s you could think about using the Visitor pattern. For your code it would mean something like this:
interface Vehicle
{
public interface Visitor<T>
{
T visit(Car car);
T visit(Truck truck);
}
<T> T accept(Visitor<T> visitor);
}
class Car implements Vehicle
{
#Override
public <T> T accept(Visitor<T> visitor)
{
return visitor.visit(this);
}
};
class Truck implements Vehicle
{
#Override
public <T> T accept(Visitor<T> visitor)
{
return visitor.visit(this);
}
};
You can then on the places where you need a distinction between the specific instances create a new Visitor, either inline or as separate class:
Vehicle.Visitor<Void> repairVisitor = new Vehicle.Visitor<Void>()
{
#Override
public Void visit(Car car)
{
carRepairService.repair(car);
return null;
}
#Override
public Void visit(Truck truck)
{
truckRepairService.repair(truck);
return null;
}
};
vehicle.accept(repairVisitor);
Please note that I made the visitor generic. You could then also have Visitors returning something.
Related
I have a class called Router that takes care of interfacing with Retrofit. So in here are all the core methods. Then i have an abstract class called ConfigurableRouter (that extends Router), that allows me to configure my router. Now i want that i can create children of the ConfigurabelRouter (In fact it is an abstract class) with different defults values.
This is an example how it works:
Router.configure(M_Rout.class)
.setPath("close-pi")
.setParams(params)
.setRequestMethod(Router.RequestMethod.POST)
.setIsAuthRequested(true)
.setCallback(new RequestResponse() {
#Override
protected void onSuccess(HashMap<String, String> responseItems) {}
#Override
protected void onGeneralError(int responseCode) {}
#Override
public void onFailure() {}
})
.sendRequest(getActivity());
This is how the Router.configure() methods work:
public static ConfigurableRouter configure(Class<? extends ConfigurableRouter> aClass){
ConfigurableRouter configurableRouter = null;
try {
configurableRouter = aClass.newInstance();
//obj is a newly created object of the passed in type
} catch (Exception ignored) { }
return configurableRouter;
}
And this is an example of a ConfigurableRouter method:
public ConfigurableRouter setParams(HashMap<Stthring, Object> params){
super.setRouterParams(params);
return this;
}
And this is the M_Router class:
public class M_Rout extends ConfigurableRouter {
#Override
public String setBasepath() {
return "www.xxxxxxx.xx/";
}
#Override
public String setInDebigBasePath() {
return "www.debugxxxxxxx.xx/";
}
#Override
public boolean isDebugging() {
return false;
}
#Override
public RequestMethod setDefultRequestMethod() {
return RequestMethod.POST;
}
#Override
public RequestResponse setDefultResponse() {
return new RequestResponse() {
#Override
protected void onSuccess(HashMap<String, String> responseItems) {
Log.d("RouterLog", "PigSUCSESSSpig");
}
#Override
protected void onGeneralError(int responseCode) {
}
#Override
public void onFailure() {
}
};
}
#Override
public ConfigurableRouter setAuthToken(String authToken) {
return super.setAuthToken("tokenExample");
}
public void setIsAuthRequested(boolean b){
//
}
}
Now my problem is that i cannot acces the non-overriden methods in M_Router class, like setIsAuthRequested(), that is in the first snippet. I have no idea how i can do.. tried in different ways but nothing. How can i do?
public abstract class Person {
abstract void sayName();
}
which has two implementations:
public class LoudPerson extends Person {
void sayName() {
System.out.println("I yell my name!!");
}
}
and
public class RegularPerson extends Person {
void sayName() {
System.out.println("I will say my name");
}
void givesBusinessCard() {
// whatever
}
}
Now, if you create a method like this:
public void handlePerson(Person person) {
}
you will be able to call the sayName() method on it, because no matter what type of Person it is, it will always have an implementation of sayName()
Now, let's say you want to pass an instance of RegularPerson, and call the givesBusinessCard(), this won't immediately work.
Even if all you ever pass as parameters are of type RegularPerson, the JVM running the code doesn't (can't) know this
Someone else could create other subclasses, and change that line of thought.
As far as the JVM knows, it's just a Person, and all Person provides is the sayName() method.
Let's say you need to be able to call the givesBusinessCard() method, you have 3 options.
Alter the method you call. If you need givesBusinessCard() to be called, you know it's a RegularPerson, so you can say:
public void handlePerson(RegularPerson person) {
}
Alter your abstract class, add the method there, and provide either a failing or an empty implementation of the method in LoudPerson
public abstract class Person {
abstract void sayName();
abstract void givesBusinessCard();
}
and
public class LoudPerson extends Person {
void sayName() {
System.out.println("I yell my name!!");
}
void givesBusinessCard() throws UnsupportedOperationException {
throw new UnsupportedOperationException("not needed here");
}
}
or
public class LoudPerson extends Person {
void sayName() {
System.out.println("I yell my name!!");
}
void givesBusinessCard() {
}
}
Cast your person to RegularPerson before calling it, but make sure to do an instance check:
public void handlePerson(Person person) {
// ..
if ( person instanceof RegularPerson ) {
RegularPerson p = (RegularPerson)person;
p.givesBusinessCard();
}
// ..
}
I want to write a method which would receive different type of objects dynamically. Once I receive the dynamic object, I have logic inside method to do something based on the properties associated with that object. It would be something like below:
MainClass{
class1 obj1;//all these are pojo
class2 obj2;
class3 obj3;
method1(<dynamic_object>)
}
method1(<dynamic_object>){
if(dynamic_object.property 1 == true){
callmethod2(dynamic_object.property 1)
}
else{
callmethod3(dynamic_object.property 1)
}
}
Here dynamic_objects are of different type.
How can I achieve this in Java? I do not want to use reflection here.
In order to recognize the type of the object you can use the instanceof operator.
private void instanceOfMethodExample(Object object){
if(object instanceof String)
print("Its a String!");
else if(object instanceof Integer)
print("Its an Int!");
else
print("Its a " + object.getClass().getName()); // by calling getClass().getName() method you take the class name of the object as a String
}
Use the visitor pattern, In a nutshell you can have something like this:
public class Visitor {
interface UserVisitor {
public void visit(CarUser user1);
public void visit(BusUser user2);
}
static class VehicleVisitor implements UserVisitor {
private Car vehicle;
private Bus bus;
VehicleVisitor(Car vehicle, Bus bus) {
this.vehicle = vehicle;
this.bus = bus;
}
public void visit(CarUser user1) {
user1.setCar(vehicle);
}
public void visit(BusUser user2) {
user2.setBus(bus);
}
}
interface UserVisitorClient {
void accept(UserVisitor visitor);
}
static class CarUser implements UserVisitorClient {
private Car car;
public void accept(UserVisitor visitor) {
visitor.visit(this);
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
}
static class BusUser implements UserVisitorClient {
private Bus bus;
public void accept(UserVisitor visitor) {
visitor.visit(this);
}
public void setBus(Bus bus) {
this.bus = bus;
}
public Bus getBus() {
return bus;
}
}
static class Car {
#Override
public String toString() {
return "CAR";
}
}
static class Bus {
#Override
public String toString() {
return "BUS";
}
}
public static void main(String[] args) {
List<UserVisitorClient> users = new ArrayList<UserVisitorClient>();
CarUser user1 = new CarUser();
users.add(user1);
BusUser user2 = new BusUser();
users.add(user2);
for (UserVisitorClient user : users) {
VehicleVisitor visitor = new VehicleVisitor(new Car(), new Bus());
user.accept(visitor);
}
System.out.println(user1.getCar());
System.out.println(user2.getBus());
}
}
Which is just an example. But it shows that basically you can use this pattern to support what you're trying to accomplish.
In your code, you could have:
void method1(VisitorClient client) {
client.accept(someVisitor);
}
This will allow you to reach o more object oriented solution, relying in polymorphism instead of reflection or instanceof.
The best option is to use a common interface
interface HasProperty {
boolean isSet();
}
void method1(HasProperty object) {
if (object.isSet())
method2(object);
else
method3(object);
}
Or even better have a method to call to perform an action.
interface MethodOne {
void method1();
}
MethodOne object = ...
object.method1(); // calls the appropriate method for this object.
Use superclass of all objects- "Object" and check the type of object using instanceof operator.
method1(Object obj){
if(obj instanceof dynamic_object){
callmethod2(dynamic_object.property 1)
}
else if(obj instanceof dynamic_object2) {
callmethod3(dynamic_object2.property 1)
}
}
EDIT: Given your newly posted code, you may even simply wish to use an common interface, or base class, for the dynamic objects.
Interface:
public interface CommonInterface {
boolean isValid();
void method1();
void method2();
void method3();
}
Class Example:
public Class1 implements CommonInterface {
public boolean isValid() {
return true;
}
public void method1() {
System.out.println("Method 1");
}
public void method2() {
System.out.println("Method 2");
}
public void method3() {
System.out.println("Method 2");
}
}
Code:
public void doSomethingWithCommonObjects(CommonInterface object) {
object.method1();
if (object.isValid()) {
object.method2();
} else {
object.method3();
}
}
Each of the dynamic objects simply need to implement the CommonInterface interface, which would enforce method1(), method2(), method3() and property1() signatures for each object to implement.
Previous answer details for reference:
You will either have to use Java Generics, potentially with some common interface or base class for the objects in question so that you can then call their methods.
E.g.
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x; // assume x is initially the largest
if (y.compareTo(max) > 0) {
max = y; // y is the largest so far
}
if (z.compareTo(max) > 0) {
max = z; // z is the largest now
}
return max; // returns the largest object
}
If, however, you require to call particular methods without knowing the interface for those methods beforehand programmatically, then you're into Reflection territory.
Here is my use case,
public interface dataModel {
//nothing
}
public interface dataRepo {
public doIt(dataModel a);
}
public class concreteDataModel implements dataModel {
public doIt(dataModel a);
}
public class concreteDataRepo implements dataRepo {
public doIt(dataModel a);
}
I feel like i am doing this wrong. I have several datarepo and datamodel. I want the repo takes the datamodel of its own kind. Is there any design pattern to make this clean?
You can use generics.
public interface dataModel {
//nothing
}
public interface dataRepo<T extends dataModel> {
public doIt(T a);
}
public class concreteDataModel implements dataModel {
public doIt(dataModel a);
}
public class concreteDataRepo implements dataRepo<concreteDataModel> {
public doIt(concreteDataModel a);
}
You could try generics:
interface dataModel { }
class concreteDataModel implements dataModel { }
interface dataRepo<E extends dataModel> {
public void doIt(E a);
}
class concreteDataRepo implements dataRepo<concreteDataModel> {
#Override
public void doIt(concreteDataModel a) {
}
}
In a project, I have a service and a class using that service. In this example case a repair service that will be used by vehicles. A repair service can only repair a certain type of vehicle: The garage can only repair cars. I need a method in the vehicle to repair it with an applicable service, repairUsingService(..).
My goal is to have a clean Vehicle base class and clean RepairService implementations. I have tried two ways of designing the repair method of the repair service:
repair(Vehicle<T> vehicle): This is ugly because implementations would need to do repair(Vehicle<Car> car) but it is obvious that a car is a vehicle.
repairSimple(T vehicle): Is nice with that but cannot be called from the Vehicle class without an ugly cast.
Is there a way to avoid casting but still only use the generic parameter type T (like in repairSimple(T))?
public class Vehicle<T extends Vehicle<T>> {
public void repairUsingService(RepairService<T> obj) {
obj.repair(this);
obj.repairSimple((T) this);
}
}
public class Car extends Vehicle<Car> {
}
public interface RepairService<T extends Vehicle<T>> {
void repair(Vehicle<T> vehicle);
void repairSimple(T vehicle);
}
public class Garage implements RepairService<Car> {
#Override
public void repair(Vehicle<Car> car) {
System.out.println("Car repaired.");
}
#Override
public void repairSimple(Car car) {
System.out.println("Car repaired.");
}
}
Could you use this implementation? This way both the vehicle knows, what repair service can repair it, and the service knows, what vehicles it can repair.
public interface RepairService<T extends Vehicle<?>> {
public void repair(T vehicle);
}
public interface Vehicle<T extends RepairService<?>> {
public void repairUsingService(T service);
}
public class Car implements Vehicle<Garage> {
#Override
public void repairUsingService(Garage service) {
}
}
public class Garage implements RepairService<Car>{
#Override
public void repair(Car vehicle) {
}
}
public class AuthorizedGarage extends Garage {
}
public class Train implements Vehicle<TrainDepot> {
#Override
public void repairUsingService(TrainDepot service) {
}
}
public class TrainDepot implements RepairService<Train> {
#Override
public void repair(Train vehicle) {
}
}
public class Test {
public static void main(String[] args) {
// this works:
new Car().repairUsingService(new Garage());
new Train().repairUsingService(new TrainDepot());
// and this works
new Garage().repair(new Car());
new TrainDepot().repair(new Train());
// but this does not (which is ok)
//new Garage().repair(new Train());
//new Car().repairUsingService(new TrainDepot());
// this also works
List<Car> cars = new ArrayList<>();
cars.add(new Car());
cars.get(0).repairUsingService(new Garage());
// this also works, if you have an expensive car ;)
new Car().repairUsingService(new AuthorizedGarage());
}
}
You could even have a base class for all your repair services to avoid code repetition:
public abstract class BaseRepairService<T extends Vehicle<?>> implements
RepairService<T> {
#Override
public void repair(T vehicle) {
}
}
Then your Garage would extend a BaseRepairService with a Car type parameter.
One way is to ask the subclass for itself:
abstract class Vehicle<T extends Vehicle<T>> {
public void repairUsingService(RepairService<T> obj) {
obj.repair(this);
obj.repairSimple(getThis());
}
abstract T getThis();
}
class Car extends Vehicle<Car> {
#Override
Car getThis(){
return this;
}
}
Let me present two reasonable alternatives.
The first is a variation of Gafter's Gadget:
public abstract class Vehicle<V extends Vehicle<V>> {
private boolean validate() {
Class<?> cls = getClass();
for(Class<?> sup;
(sup = cls.getSuperclass()) != Vehicle.class;
cls = sup
);
Type sup = cls.getGenericSuperclass();
if(!(sup instanceof ParameterizedType))
return false;
Type arg = ((ParameterizedType)sup).getActualTypeArguments()[0];
if(!(arg instanceof Class<?>))
return false;
return ((Class<?>)arg).isInstance(this);
}
protected Vehicle() {
assert validate() : "somebody messed up";
}
}
Since Vehicle is always parameterized by a subclass, it's OK to use this idiom. During development you run with assertions on and the constructor will throw an error if somebody extends the class incorrectly.
Now the unchecked cast is always safe.
The second is that RepairService no longer carries a type parameter. Instead, you keep a listing of Class<? extends Vehicle> the RepairService can repair.
public interface RepairService {
boolean canRepair(Vehicle v);
// if v can't be repaired, perhaps repair
// throws an exception or returns boolean instead of void
void repair(Vehicle v);
}
public class ServiceStation implements RepairService {
private final List<Class<? extends Vehicle>> types;
public ServiceStation(Class<? extends Vehicle>... types) {
this.types = Arrays.asList(types);
}
#Override
public boolean canRepair(Vehicle v) {
for(Class<? extends Vehicle> c : types) {
if(c.isInstance(v))
return true;
}
return false;
}
#Override
public void repair(Vehicle v) {
if(!canRepair(v))
throw new IllegalArgumentException();
// impl
}
}
At least for the Vehicle/RepairStation analogy this is probably much more usable than trying to force generics in to the design. Vehicle probably doesn't need a type parameter either anymore.
Maybe your actual program is different but you should always consider whether straight program logic solves the problem before introducing a parametric design. Trying to force generics to work in a situation where they are a suboptimal solution gets very awkward.
I have the following code
public abstract class Event {
public void fire(Object... args) {
// tell the event handler that if there are free resources it should call
// doEventStuff(args)
}
// this is not correct, but I basically want to be able to define a generic
// return type and be able to pass generic arguments. (T... args) would also
// be ok
public abstract <T, V> V doEventStuff(T args);
}
public class A extends Event {
// This is what I want to do
#Overide
public String doEventStuff(String str) {
if(str == "foo") {
return "bar";
} else {
return "fail";
}
}
}
somewhere() {
EventHandler eh = new EventHandler();
Event a = new A();
eh.add(a);
System.out.println(a.fire("foo")); //output is bar
}
However I don't know how to do this, as I cannot override doEventStuff with something specific.
Does anyone know how to do this?
It's not really clear what you're trying to do, but perhaps you just need to make Event itself generic:
public abstract class Event<T, V>
{
public abstract V doEventStuff(T args);
}
public class A extends Event<String, String>
{
#Override public String doEventStuff(String str)
{
...
}
}
You're using generics but you are not providing a binding.
public abstract class Event<I, O> { // <-- I is input O is Output
public abstract O doEventStuff(I args);
}
public class A extends Event<String, String> { // <-- binding in the impl.
#Override
public String doEventStuff(String str) {
}
}
Or simpler with only one generic binding...
public abstract class Event<T> { // <-- only one provided
public abstract T doEventStuff(T args);
}
public class A extends Event<String> { // <-- binding the impl.
#Override
public String doEventStuff(String str) {
}
}