Imagine you have a menu with dishes each dish should be available in multiple languages (French , English , Arabic , ...). The Dish
class contains a list with Language
type objects.
class Dish {
List<Language> languages
void addLanguage(Language lg){...}
}
class Language { getDescription(){}}
class French extends Language{}
class Menu {List<Dish> dishes }
How do I avoid using instance of
when wanting a description of a specific language for that dish?
Should I define for each language a get method in the dish class:getFrench(), getArabic(),..?
Or should I keep it in list and check for instance of French by looping the list and then call getDescription()
on this list object<language>
?
Or is there a way for a more polymorphic approach?
Yes, in general using `instanceof`` is a symptom of a bad/poor design. The trick is to use double dispatch or visitor pattern. Look on the web. It would be easier to give you some examples if you included a bit of detail about how you are using instanceof .
The primary alternative to using instanceof is polymorphism. Rather then ask which type of object you have at the current position you tell the object, whatever it is, to do what you want done. If both objects know how to do that then this works fine, even if they do it differently.
The instanceof in java is also known as type comparison operator because it compares the instance with type. It returns either true or false. If we apply the instanceof operator with any variable that has null value, it returns false.
The instanceof operator in Java is used to check whether an object is an instance of a particular class or not. objectName instanceOf className; Here, if objectName is an instance of className , the operator returns true . Otherwise, it returns false .
I don't think it's a good idea to create a separate class for each language. After all, all these classes will have the exact same methods.
I'd use a single Language
class, and inside the Dish
class I'll keep a Map<Locale,Description>
(I'd rename the Language
class to something less confusing such as Description
, since it doesn't represent a language, it represents a description in some language).
Now you can have a
Description getDescription(Locale locale)
method in your Dish
class, which will return the description of the dish in the language of the passed Locale
.
You should prefer using standard JDK classes such as java.util.Locale
instead of custom classes when possible.
After considering the comments, and agreeing to some of them, I suggest removing the Map
to the Description
class.
class Dish
{
Description description = new Description ();
void addDescription(Locale locale, String text)
{
description.addText(locale,text);
}
String getDescription(Locale locale)
{
return description.getText(locale);
}
}
class Description
{
Map<Locale,String> descriptions = new HashMap<>();
public void addText(Locale locale,String text)
{
descriptions.put(locale,text);
}
public void getText(Locale locale)
{
return descriptions.get(locale);
}
}
You should also note that searching the language specific description in a Map
is more efficient than searching for it in a List
(O(1)
lookup time in a HashMap
vs. O(n)
lookup time in a List
).
I think a Language
doesn't have a menu Description
. I would design it in this way.
class Dish {
List<Description> descriptions;
void addDescription(Description description){...}
Description getDescription(Language language){
// iterate over descriptions and select the appropriate
// or use a Map<Language, Description>
Optional<Description> applicableDescription =
descriptions.stream()
.filter(d -> d.getLanguage().isApplicable(language)).findFirst();
return applicableDescription.orElseGet(this::getDefaultDescription);
}
private Description getDefaultDescription(){
return descriptions.isEmpty() ? null : descriptions.get(0);
}
}
class Description {
Language language;
String shortDescription;
String title;
// and so on...
public boolean isApplicable(Language language){
return this.language.equals(language);
// This logic can be more sophisticated. E.g. If an Italian
// wants to get a menu description, but no italian translation is
// available, it might be useful to choose spanish. But then it
// would be better to return a similarity, like 0.1 to 1.0, instead of true/false.
}
}
class Language {
String name; // like en, de, it, fr, etc. Maybe an enum is better or just using
// java.util.Locale
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With