Suppose I have a class hierarchy in Java:
interface Item { ... };
class MusicBox implements Item { ... };
class TypeWriter implements Item { ... };
class SoccerBall implements Item { ... };
and I have another class in the same package:
class SpecialItemProcessor {
public void add(Item item)
{
/* X */
}
}
where I want to do something different for each item type, but I don't want to define that action in the different Item classes (MusicBox, TypeWriter, SoccerBall).
One way to handle this is:
class SpecialItemProcessor {
public void add(Item item)
{
if (item instanceof MusicBox)
{
MusicBox musicbox = (MusicBox)item;
... do something ...
}
else if (item instanceof MusicBox)
{
TypeWriter typewriter = (TypeWriter)item;
... do something ...
}
else if (item instanceof SoccerBall)
{
SoccerBall soccerball = (SoccerBall)item;
... do something ...
}
else
{
... do something by default ...
}
}
}
This works but it seems really clunky. Is there a better way to do this, when I know of special cases? (obviously if Item contains a method doSomethingSpecial then I can just call that item's method without caring what type it is, but if I don't want that differentiation to occur within the item itself how do I deal with it?)
In Java you can do multiple dispatch with a visitor(-like) pattern. The Item implementations don't need to contain the processing logic, they just need an accept() type of method.
public interface Item {
/** stuff **/
void processMe(ItemProcessor processor);
}
public interface ItemProcessor {
void process(MusicBox box);
void process(SoccerBall ball);
//etc
}
public class MusicBox implements Item {
#Override
public void processMe(ItemProcessor processor) {
processor.process(this);
}
}
public class ItemAddingProcessor implements ItemProcessor {
public void add(Item item) {
item.processMe(this);
}
#Override
public void process(MusicBox box) {
//code for handling MusicBoxes
//what would have been inside if (item instanceof MusicBox) {}
}
//etc
}
I think I'm going to use the idea of inversion of control and the visitor pattern:
interface Item {
public void accept(Visitor visitor);
...
public interface Visitor {
public void visit(Item item);
}
}
class MusicBox implements Item {
public interface Visitor extends Item.Visitor {
public void visitMusicBox(MusicBox item);
}
...
#Override public accept(Item.Visitor visitor)
{
if (visitor instanceof MusicBox.Visitor)
{
((MusicBox.Visitor)visitor).visitMusicBox(this);
}
}
}
class TypeWriter implements Item {
public interface Visitor extends Item.Visitor {
public void visitTypeWriter(TypeWriter item);
}
...
#Override public accept(Item.Visitor visitor)
{
if (visitor instanceof TypeWriter.Visitor)
{
((TypeWriter.Visitor)visitor).visitTypeWriter(this);
}
}
}
class SoccerBall implements Item {
public interface Visitor extends Item.Visitorr {
public void visitSoccerBall(SoccerBall item);
}
...
#Override public accept(Item.Visitor visitor)
{
if (visitor instanceof SoccerBall.Visitor)
{
((SoccerBall.Visitor)visitor).visitSoccerBall(this);
}
}
}
and then do the following, which at least reduces the instanceof to one check per add() call:
class SpecialItemProcessor
implements
MusicBox.Visitor,
TypeWriter.Visitor,
SoccerBall.Visitor,
Item.Visitor
{
public void add(Item item)
{
item.accept(this);
}
#Override public void visitMusicBox(MusicBox item)
{
...
}
#Override public void visitTypeWriter(TypeWriter item)
{
...
}
#Override public void visitSoccerBall(SoccerBall item)
{
...
}
#Override public void visit(Item item)
{
/* not sure what if anything I should do here */
}
}
Why not define some callback function to Item interface?
public Interface Item {
void onCallBack();
}
Then in each class that implements Item, such as MusicBox, it should implement the callback function.
public class MusicBox {
#override
public void onCallBack() {
// business logic
...
...
}
}
Then you could create a dispatcher, which you name is "SpecialItemProcessor".
public SpecialItemProcessor {
private final Item _item;
public SpecialItemProcessor(Item item) {
_item = item;
}
public dispatch() {
_item.onCallBack()
}
}
And then, in the Client class which contains the SpecialItemProcessor could just call the method, like:
public void XXXX() {
....
SpecialItemProcessor specialItemProcessor = new SpecialItemProcessor(new MusicBox());
specialItemProcessor.dispatch();
....
}
Actually, in C++, this is Dynamic Binding. And this is why pure abstract class exists...
You could create a bridge pattern for Item, in which the other side were the associated processes to do when add() is called. You could also add a factory method to the mix.
class SpecialItemProcessor {
public void add(Item item)
{
Process p = Item.createCorrespondingProcessor( p );
p.doWhenAddin();
}
}
Hope this helps.
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 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.
I'm doing a project that should be stored in two differents text files. Let say I have 2 classes Person and Activity, each with only these attributes in common: id and isActive. But there are also many that are not common.
Also I have 2 classes ArrayList type:
public class RegistryPerson extends ArrayList<Person> {
public void add(Person obj){
....
}
public boolean isDuplicate(Person obj){
for(Person p: this){
if(obj.equals(p)){
return true;
}
}
return false;
}
public Person search(int id){
....
}
public void readFile(){
otherClass.readFile(String txtfilePerson);
}
public void activate(Person obj){
obj.setActivate;
}
//more methods
}
.
public class RegistryActivity extends ArrayList<Activity> {
public void add(Activity obj){
....
}
public boolean isDuplicate(Activity obj){
for(Activity p: this){
if(obj.equals(p)){
return true;
}
}
return false;
}
public Activity search(int id){
....
}
public void readFile(){
otherClass.readFile(String txtfileActivity);
}
public void activate(Activity obj){
obj.setActivate;
}
//more methods
}
Both classes have the same methods
As you see both classes type ArrayList RegitryPerson and RegistryActivigy have same methods, but some used different kind of object.
I just don't wanna have almost same code in differents classes. Can I use an interface or abstract class? and most important, How can implement that?. Or I am complicating everything?
Thanks.
You can follow Program to an interface, not implementations design principle here.
Create an interface say Entity that would be implemented by both Person and Activity
Entity.java
public interface Entity {
public Boolean equals(Entity e);
//other common methods
}
This interface would be implemented by both Person and Activity
Person.java
public class Person implements Entity {
...
#Override
public boolean equals(Entity e) {
...
}
...
}
Activity.java
public class Activity implements Entity {
...
#Override
public boolean equals(Entity e) {
...
}
...
}
Now create a parent Class Registry
Registry.java
public class Registry extends ArrayList<Entity> {
public void add(Entity obj){
....
}
public boolean isDuplicate(Entity obj){
for(Entity p: this){
if(obj.equals(p)){
return true;
}
}
return false;
}
public Entity search(int id){
....
}
public void readFile(){
otherClass.readFile(String txtfilePerson);
}
public void activate(Entity obj){
obj.setActivate;
}
//more methods
}
Now you can extend this Registry class to both of your implementations, i.e., RegistryPerson and RegistryActivity
RegistryPerson.java
public class RegistryPerson extends Registry {
..
}
RegistryActivity.java
public class RegistryActivity extends Registry {
..
}
P.S.: All of the classes listed above many contain more common methods. This is just to give you basic introduction to this design principle.
I had the same idea as rD but used generics to create the registry. I also moved the List inside the class. Methods to read from file and add the registry could be handled by other classes. I try to avoid inheritance and abstract classes at all costs. Interfaces are generics are quite powerful.
interface IdObject {
int getId();
}
class Registry<T extends IdObject> {
private List<T> list = new ArrayList<T>();
public void add(T obj){
list.add(obj);
}
public boolean isDuplicate(T obj){
for(T t: list){
if(obj.equals(t)){
return true;
}
}
return false;
}
public T search(int id){
for(T t: list){
if(t.getId() == id)){
return t;
}
}
return null;
}
}
class Example {
Registery<Person> personRegistery = new Registry<>();
Registery<Activity> activityRegistery = new Registry<>();
}
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) {
}
}
I'm using the Observable class / Observer interface in Java to implement the observer pattern. The Observer interface requires overwriting the update(Observable o, Object arg) method.
The problem is that I'm observing a fair number of classes, and my update() method has gotten very large:
public class Foo implements Observer {
....
public void update(Observable o, Object param) {
if (o instanceof A) {
// large chunk of code
...
} else if (o instanceof B) {
// large chunk of code
...
}
...
} else if (o instanceof H) {
...
}
}
}
In order to split up the method, I'm thinking of extending the Observer interface with e.g. AObserver interface, BObserver interface.. which requires overwriting onAUpdate, onBUpdate .. respectively. This method will also make it easy to determine what Observables the class is observing based on the interfaces it's implementing.
class Foo implements AObserver, BObserver {
....
public void onAUpdate(Observable o, Object param) {
if (o instanceof A) {
// large chunk of code
...
}
public void onBUpdate(Observable o, Object param) {
if (o instanceof B) {
// large chunk of code
...
}
}
The problem is that if I inherit Observer, I still have to implement the update() method. I can't rename it to onAUpdate or some other name of my choosing.
Any advice? Thanks.
I'll suggest to create an UpdateHandler interface to do the processing for any given code block. Each case can be handle with a map.
Sample code follows:
// Interface to implement for each case
public interface UpdateHandler {
public void update(Observable source, Object data) ;
}
Add an instance field to your main class as follows:
private Map<Class<?>, UpdateHandler> handlers = new HashMap<Class<?>, Update Handler>();
Create a method to have the handlers initialized
protected void initializeHandler() {
handler.put(Integer.class, new IntegerUpdateHandler());
handler.put(String.class, new StringUpdateHandler());
...
}
The updates method will simply find the appropriate handler and dispatch the call
public void update(Observable source, Object data)
{
UpdateHandler handler = handlers.get(data.getClass()) ;
if (handler == null)
{
// use a default handler ? throw an exception ? your choice ;)
} else {
handler.update(source, data) ;
}
}
This implementation will allow you to add new handler as needed with minimal changes.
Another possible implementation can be done base on the previous work, just a 3 step procedure.
1) Change the declaration of the handlers field.
Map<Class<?>, Class<? extends UpdateHandler>> handlers ;
2) change the initialize method
handlers.put(Integer.class, IntegerInputHandler.class);
3) change the main update method to create a new instance of the provided UpdateHandler implementation.
UpdateHandler handlerInstance = null ;
Class<? extends UpdateHandler> handler = null ;
handler = handlers.get(data.getClass()) ;
...
handlerInstance = handler.newInstance() ;
handlerInstance.update(source, data) ;
Here I coded a raw implementation using observer and visitor pattern. You can take this as an idea to enhance upon it and to fill wherever you see some holes.
public interface IObserver extends Observer {
public void add(AbstractObservable observable, IObserverVisitor visitor);
public void remove(AbstractObservable observable);
public void removeAll();
}
public class Observer implements IObserver {
Map<AbstractObservable, IObserverVisitor> observableMap =
new HashMap<AbstractObservable, IObserverVisitor>();
public void add(AbstractObservable observable, IObserverVisitor visitor) {
observableMap.put(observable, visitor);
}
public void remove(AbstractObservable observable) {
observableMap.remove(observable);
}
public void removeAll() {
observableMap.clear();
}
public void update(Observable o, Object arg) {
observableMap.get(o).visit(this, o, arg);
}
}
public class AbstractObservable extends Observable{
public synchronized void addObserver(IObserver o, IObserverVisitor visitor) {
o.add(this, visitor);
super.addObserver(o);
}
public synchronized void deleteObservers(IObserver o) {
o.removeAll();
super.deleteObservers();
}
public synchronized void deleteObserver(IObserver o) {
o.remove(this);
super.deleteObserver(o);
}
#Override
public synchronized void deleteObserver(Observer o) {
throw new UnsupportedOperationException();
}
#Override
public synchronized void addObserver(Observer o) {
throw new UnsupportedOperationException();
}
#Override
public synchronized void deleteObservers() {
throw new UnsupportedOperationException();
}
#Override
public synchronized int countObservers() {
return super.countObservers();
}
#Override
public synchronized boolean hasChanged() {
return super.hasChanged();
}
#Override
public void notifyObservers() {
super.notifyObservers();
}
#Override
public void notifyObservers(Object arg) {
super.notifyObservers(arg);
}
#Override
protected synchronized void clearChanged() {
super.clearChanged();
}
#Override
protected synchronized void setChanged() {
super.setChanged();
}
}
public class Observable1 extends AbstractObservable {
public void changeSomething() {
setChanged();
notifyObservers();
}
}
public class Observable2 extends AbstractObservable {
public void changeSomething() {
setChanged();
notifyObservers();
}
}
public interface IObserverVisitor {
void visit(IObserver obsrvr, Observable obsrvable, Object o);
}
public class ObserverVisitor1 implements IObserverVisitor{
public void visit(IObserver obsrvr, Observable obsrvable, Object o) {
System.out.println("updated one");
}
}
public class ObserverVisitor2 implements IObserverVisitor{
public void visit(IObserver obsrvr, Observable obsrvable, Object o) {
System.out.println("updated two");
}
}
public class ObserverTest {
#Test
public void testAnything() {
Observable1 obsrvable1 = new Observable1();
Observable2 obsrvable2 = new Observable2();
Observer obsrvr = new Observer();
obsrvable1.addObserver(obsrvr, new ObserverVisitor1());
obsrvable2.addObserver(obsrvr, new ObserverVisitor2());
obsrvable1.changeSomething();
obsrvable2.changeSomething();
}
}
I hope you are not lost. :)
Move the chunks of code within each condition to appropriately named methods.
public void update(Observable o, Object param) {
if (o instanceof A) {
onAUpdate(o, param);
}
if (o instanceof B) {
onBUpdate(o, param);
}
}
public void onAUpdate(Observable o, Object param) {
// large chunk of code
}
public void onABUpdate(Observable o, Object param) {
// large chunk of code
}