简体   繁体   中英

Generic object factory

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?

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));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM