represent identifier hierarchy - java - java

I have a need to have XYZIdentifier object which will be used in composition in other class to identify the object.
However, Depending on the use-case (a variable in the client object), the identifier can be either a String, long, or even a Class.
Something like IntegerIdentifier, StringIdentifier, FooIdentifier and some interface defined which can be generic.
How can I create this design?

Not sure what your full context is, but part of the solution may involve generics to fetch the kind of result you need, like:
public <T extends IdentifierBase> T getIdentifier(Class<T> kindYouWant) { ... }
The idea being you tell it which flavor you need, and it could either convert with best-effort, or return Null if that kind isn's available.
Like I said, not sure of your whole question...

Related

Most efficient way to remove duplicated code from multiple strategies

We have 3 types of attributes in our project: CategoryAttribute, ProductAttribute and ProductTypeAttribute. These are outside of our control as they come from autogenerated classes and may contain attribute values of different types e.g. text, number or image. Now, each attribute has its own strategy to retrieve attributeValue. For simplicity, let's assume that all 3 of them have TextStrategy, NumberStrategy and ImageStrategy.
Example strategy:
#Component
public class CategoryImageAttributeStrategy implements CategoryAttributeStrategy {
#Override
public boolean isApplicable(CategoryAttribute attribute) {
return attribute.getImage() != null;
}
#Override
public Object getAttributeValue(CategoryAttribute attribute) {
//return attribute value here
//may be different or may be the same
//for ProductImageAttributeStrategy and ProductTypeImageAttributeStrategy
}
}
While getting image value may be different for all of them, getting text value is the same and we end up with 3 classes of almost the same code and I really really really don't like duplicating code.
I thought about creating an abstract class/default interface for each strategy type e.g. DefaultTextStrategy that all 3 text strategies would inherit from and either use default code provided higher or override it with own implementation, however I'm not really satisfied with this approach as it requires to create even more classes for such a simple task.
Maybe is it even possible to combine strategies of the same type (e.g. image) into one?
I would really like to hear what more experienced folks have to say in this matter as I would like to learn and improve.
Thanks in advance for your time.
There should be only 3 strategies. TextStrategy, NumberStrategy and ImageStrategy which extend the base strategy. Mixing attributes and strategy will make it confusing as both are actually independent and have many to many relationship with one another.
Let the 3 attributes extend a single Attribute class : CategoryAttribute, ProductAttribute and ProductTypeAttribute.
Let the strategies decide on what needs to be done based on the Attribute class object being passed to it. For Text strategy there would be single implementation. For Image strategy, you may require special handling for the one class.
Here's what I did:
First, I created an interface for all types of strategies named "AttributeValueStrategy". Then added 3 callbacks (type specific, e.g. NumberValueCallback etc.). Now, each strategy implements callback interface of its type and AttributeValueStrategy interface. Then there's DefaultStrategyMethods class that contains default "getAtrribute" for each type and the actual strategy call the defaultStrategyMethods (like below) or just implements its own code.
#Override
public Object getAttributeValue(Object attribute) {
return defaultStrategyMethods.getNumberValue(attribute, this);
}
Callbacks are created because only the actual strategy knows which class should it cast to (and has a method to do that), and DefaultStrategyMethods needs to use it so that's why I pass "this" as second argument (which is the callback itself).
No more duplicates, everything is clear and clean.

Instantiating object without knowing the concrete type

I am creating following java class.
class EntityCollection <E extends Entity, M extends Hashmap<?,E>> {
}
The idea is that the user of this class will tell me what type of objects to save in the collection and the actual store. So M can be simple Hashmap or LinkedHashmap.
I have two questions here:
How would I instantiate M inside my class? Is it possible?
AND
Is this a good approach or should I take some StoreFactory that would return me the store to use? Should I take that in the constructor of this class?
You can't do this the way you're set up due to type erasure. You can pull it off by having them pass the class to you.
Give this a read:
Create instance of generic type in Java?
Creating the hashmap is easy, you just pass the generic types through - or even use the diamond notation and have it done for you.
M m = new HashMap<>();
The complication is that you want to also be able to select the type of the Map. That can be done in a number of ways:
You could use the Factory pattern and pass in a factory object that creates the maps on demand.
You could generate the Map outside the class and pass it in on the constructor.
Have an abstract method to create the map. When creating an instance of the class people would implement that abstract method and generate the map for it.
For the second question there's no way to know without a lot more detail of what you are doing. That's an architectural decision and would most likely not fit into a stack overflow Q & A. This all seems a bit messy though, you are exposing a lot of the internal behavior of the classes. You would probably be better off thinking more about the behavior you want and the interface to provide that rather than the details of implementation.
For example you could have an enum { UNSORTED, INSERTION_ORDER, etc } and then instantiate the right Map based on that enum.

Using generics to avoid looping and casting

I have an Object Conversion Class that converts from my domain level objects to DTOs.
I effectively have the following structure
class RuleGroupDTO {
List<RuleDTO> ruleDTOs;
// other members
EvaluationRuleDTO and AssignmentRuleDTO both extend from RuleDTO
My API for conversion is as follows:
public RuleGroupDTO convert(RuleGroup ruleGroup);
So when I pass in my domain RuleGroup to the convert class, it looks at a code associated with the RuleGroup and then constructs either EvaluationRuleDTO or AssignmentRuleDTOs encapsulated within the RuleGroupDTO.
When I retrieve back my RuleGroupDTO, I know that it will contain a List<RuleDTO> that is either List<EvaluationRuleDTO> or List<AssignmentRuleDTO>.
However, to get the correct class version I need to loop through the List<RuleDTO> and cast to either List<EvaluationRuleDTO> or List<AssignmentRuleDTO>
This seems messy, and I am thinking that I can leverage some generic concepts to avoid performing this loop + cast.
What would be a possible approach to changing my API or object structure to take advantage of generics here?
If you have a set amount of types and you want them separate, then return a pojo with the various types separated into different collections, e.g.:
public class DTOResult {
public List<EvaluationRuleDTO> evalDTOs;
public List<AssignmentRuleDTO> assignDTOs;
}
Use List<RuleDTO> to avoid casting, and for god's sake don't write a loop. Make RuleDTO implement a visitor pattern that allows any consumer to handle either kind of subclass in a type-safe manner.
Java sucks at variant types.

Java bounded generic constraints on fields

There have been a couple of times when I've felt the need to do something like the following:
private <T extends Type> Map<GenericClass1<T>,GenericClass2<T>> map;
...or something to that effect. Essentially, using an identical bound in the two arguments for map. (This isn't an actual example, just shows the idea.)
I know this (unfortunately) isn't possible and that it's only available on class definitions and method signatures. My question however is why isn't it available on fields? Is it purely a design choice or is there some technical reason behind it that I'm missing? I've had a think and can't see why this shouldn't be possible from a technical perspective, as far as I can see everything is there for the compiler to work it out correctly and none of the generic information is required at runtime.
<T> means ONE class, not A class.
When your object is instanced T is bound to this ONE class.
You are trying to put two objects with diffrent interfaces (used diffrently because they take/return diffrent types) in to the same container. This is a error because when you take them out of the container (the map) you dont know what it was you put in.
Hope this is the answer you were looking for.
Edit: That said you can have a container that holds members based on there class, to automatically create a new map for EACH type of T. You would then need to know what T was in order to access it.
In general, if you dont want the type information anymore, throw it away. If you do then putting it in the same container as something of another type will throw it away anyway for all practical reasons.
Let's assume that you want to instantiate your map variable. Theoretically you will have to write something like this:
map = new HashMap<GenericClass1<String>,GenericClass2<String>>();
Ok. But now what does not make sense to me anymore is what arguments the put or get methods will accept/return? T? Uh... what is T? GenericClass1|2<String>? Again makes no sense, does it? After all I see no String in the map declaration. So I guess there is no really correct instantiation and usage of this generic variable.
Cheers!
Oh, how I have longed for something like:
private <T> Map<Class<T>, T> instanceCache;
public <T> T getInstanceOf(Class<T> clazz) {
return instanceCache.get(clazz);
}
But as you mentioned, it's completely impossible in Java. The method declaration above is fine, but there's no way to declare the variable such that there's not a cast in the method. Simply add this to the growing list of things you hate about generics and move on.
You can use ? as following:
private List<? extends List> l = new ArrayList<List>();
I hope this helps.

Type aliases for Java generics

I have a fairly complicated set of generic classes in Java. For example, I have an interface
interface Doable<X,Y> {
X doIt(Y y);
}
and the implementation
class DoableImpl implements Doable<Foo<Bar<Baz,Qux>>,Foo<Bar<Zot,Qux>>> {
Foo<Bar<Baz,Qux>> doIt(Foo<Bar<Zot,Qux>> fooBZQ) { ... }
}
In the real implementation, Doable has quite a few methods and so Foo<Bar<Baz,Qux>>, etc., appear over and over again.
(Believe it or not, the generic types are quite a bit more painful than this. I've simplified them for the example.)
I'd like to simplify these, to save myself typing and to ease the strain on my eyes. What I'd like is to have a simple "type alias" for Foo<Bar<Baz,Qux>>, etc., say FooBBQ and FooBZQ.
My current idea is to define wrapper classes:
class FooBBQ {
public static FooBBQ valueOf(Foo<Bar<Baz,Qux>> fooBBQ) {
return new FooBBQ(fooBBQ);
}
private Foo<Bar<Baz,Qux>> fooBBQ;
private FooBBQ(Foo<Bar<Baz,Qux>> fooBBQ) {
this.fooBBQ = fooBBQ;
}
public Foo<Bar<Baz,Qux>> toGeneric() {
return fooBBQ;
}
}
class FooBZQ { /* pretty much the same... */ }
class DoableImpl implements Doable<FooBBQ,FooBZQ> {
FooBBQ doIt(FooBZQ fooBZQ) { ... }
}
This works well, but it has a few drawbacks:
We need to define separate wrappers for each generic instance. The wrapper classes are short and stylized, but I can't figure out a way to macro-ize them.
We have the translation overhead (conceptually, if not operationally) of calling valueOf and toGeneric to convert between FooBBQ and Foo<Bar<Baz,Qux>>. For example, if doIt calls into some library routine that expects a Foo<Bar<Zot,Qux>> (which the real implementation does), we end up with something like
return FooBBQ.valueOf( libraryCall( fooBZQ.toGeneric() ) )
where we would originally have had
return libraryCall(fooBZQ);
Is there some other way to get the "type alias" behavior I want here? Perhaps using some third-party macro toolset? Or do I need to accept that I'm going to have to do a lot of typing, one way (using the generic types in the implementation) or the other (writing wrappers for them)? Maybe having this many generic parameters flying around is just a bad idea and I need to re-think the problem?
[UPDATE] OK, I'm banning any further "don't do that" answers. Take it as a given that Foo<Bar<Baz,Qux>> has genuine value in my problem domain (Pete Kirkham may be right that it has enough value to get a proper wrapper class with a descriptive name). But this is a programming problem; don't try to define the problem away.
If you want full type safety, I don't think you can do better without some kind of wrapper classes. But, why not make those classes inherit/implement the original generic versions, like this:
public class FooBBQ extends Foo<Bar<Baz,Qux>> {
...
}
This eliminates the need for toGeneric() method, and it is more clear, in my opinion, that it is just a type alias. Also, generic type can be cast into FooBBQ without a compiler warning. It would be my personal preference to make Foo, Bar, Baz... interfaces, if possible, even if some code duplication would occur in implementation.
Now, without knowing concrete problem domain, it is hard to say whether you need, say FooBBQ, like in your example, or perhaps a:
public class FooBar<X, Y> extends Foo<Bar<X, Y>> {
...
}
On the other hand, have you thought about simply configuring Java compiler not to show some of the generic warnings, and simply omit the parts of generic definition? Or, use strategically placed #SuppressWarnings("unchecked")? In other words, can you make DoableImpl only "partly genericized":
class DoableImpl implements Doable<Foo<Bar>>,Foo<Bar>> {
Foo<Bar> doIt(Foo<Bar> foobar) { ... }
}
and ignore the warnings for the sake of less code clutter? Again, hard to decide without a concrete example, but it is yet another thing you can try.
Scala has nice support for type aliases. For example:
type FooBBQ = Foo[Bar[Baz,Qux]]
I realize that this answer won't be helpful if you don't have the option of switching to Scala. But if you do have the option of switching you might have an easier time.
Maybe having this many generic parameters flying around is just a bad idea and I need to re-think the problem?
Very probably. Do need to specialise 'Doit' in 8 dimensions?
In a lot of cases, these types don't exist in a vacuum and you should be thinking what domain objects your 'wrapper' represents rather than using them as a coding convenience.
Well, Java has no type aliases so you're out of luck. However, type aliases sometimes can be replaced with type variables! So we solve the problem of too many generics with even more generics!
As you've stripped all content from your example I can't guess where or whether it makes sense to introduce additional type variables, but here is one possible decomposition:
class DoableImplFoo<A,B> implements Doable<Foo<A>,Foo<B>> {
public DoableImplFoo(SomePropertyOf<A,B> aAndBAreGoodEnough) { ... }
Foo<A> doIt(Foo<B> fooB) { ... }
}
When you instantiate A to Bar<Baz,Qux> and B to Bar<Zot,Qux> later you may find that there is some boilerplate again, but it could be less than what you originally had.
I would say that, yes, you need to rethink the problem. The declaration
class DoableImpl implements Doable<Foo<Bar<Baz,Qux>>,Foo<Bar<Zot,Qux>>> {
Foo<Bar<Baz,Qux>> doIt(Foo<Bar<Zot,Qux>> fooBZQ) { ... }
}
is a pretty clear case of overusing generics.

Categories

Resources