Reputation: 557
I got several objects that are created based on DataObject
class.
So I'd like to make generic factory to construct them.
I'v tried something like this:
interface FactoryObject<T> {
T create(DataObject data);
}
public class Factory {
List<FactoryObject> fromDataObjectArray(DataObject[] data, Class<? extends FactoryObject> cls) {
return Arrays.stream(Optional.ofNullable(data).orElse(new DataObject[0]))
.map(d -> cls.create()).collect(Collectors.toList());
}
}
Finally, I'd like to call
List<MyClass> myClasses = Factory.fromDataObjectArray(data, MyClass.class);
But method create()
cannot be resolved, how can I achieve what I need?
Upvotes: 0
Views: 363
Reputation: 9650
If I understand you code, you want to create a list of instances; you could do something like that:
<T> List<T> fromDataObjectArray(DataObject[] data, FactoryObject<T> fac) {
return Arrays.stream(Optional.ofNullable(data).orElse(new DataObject[0]))
.map(d -> fac.create(d)).collect(Collectors.toList());
}
UPDATE:
If I understand your comment below, you want a composite factory that will determine from a DataObject
what is the actual factory you want to use to create your instance.
You could do something like this:
public class CompositeFactory<T> implements FactoryObject<T> {
private final Function<DataObject,FactoryObject<? extends T>>[] funcs;
public CompositeFactory(
Function<DataObject,FactoryObject<? extends T>>... funcs) {
this.funcs = funcs;
}
@Override
public T create(DataObject data) {
for (Function<DataObject,FactoryObject<? extends T>> func: funcs) {
FactoryObject<? extends T> fac = func.apply(data);
if (fac != null) {
return fac.create(data);
}
}
return null; // or throw an exception
}
}
Another way to do that is conditional factories:
public class ConditionalFactory<T> implements FactoryObject<T> {
private final Predicate<DataObject> cond;
private final FactoryObject<? extends T> ifFac;
private final FactoryObject<? extends T> elseFac;
public ConditionalFactory(Predicate<DataObject> cond,
FactoryObject<? extends T> ifFac,
FactoryObject<? extends T> elseFac) {
this.cond = cond;
this.ifFac = ifFac;
this.elseFac = elseFac;
}
@Override
public T create(DataObject data) {
return (cond.test(data) ? ifFac : elseFac).create(data);
}
}
UPDATE 2:
Exemple: let's say you have the following classes:
class MyClass1 extends MyClass {
public MyClass1(DataObject data) {
}
}
class MyClass2 extends MyClass {
public MyClass2(DataObject data) {
}
}
...
and the corresponding factories:
FactoryObject<MyClass1> fac1 = (data) -> new MyClass1(data);
FactoryObject<MyClass2> fac2 = (data) -> new MyClass2(data);
FactoryObject<MyClass3> fac3 = (data) -> new MyClass3(data);
...
and let's say you can determine the actual class from the value of DataObject.getType()
:
You could do:
FactoryObject<MyClass> fact = new CompositeFactory<MyClass>(
(data)-> data.getType().equals("value1") ? fac1 : null,
(data)-> data.getType().equals("value2") ? fac2 : null,
(data)-> data.getType().equals("value3") ? fac3 : null,
...
);
you could also do:
FactoryObject<MyClass> fac = new CompositeFactory<MyClass>(
(data)->{
switch (data.getType()) {
case "value1":
return fac1;
case "value2":
return fac2;
...
default:
return null;
}
});
or:
FactoryObject<MyClass> fac = new ConditionalFactory<MyClass>(
(data)->data.getType().equals("value1"), fac1,
new ConditionalFactory<MyClass>(
(data)->data.getType().equals("value2"), fac2,
fac3));
Upvotes: 1