Is java 8 supplier replacing constructor call

Irindul :

I've been looking at the Supplier and Consumer interfaces of Java 8 and of what I understand it can replace constructor call.
I've seen an example on dzone (link here) where a ShapeFactory is used. The code is pretty simple, a simple factory for a shape class.
But she uses it as so :

Supplier<ShapeFactory> supplier = ShapeFactory::new;
supplier.get().getShape("rectangle").draw(); 

But why is it better than doing a simple classical :

ShapeFactory factory = new ShapeFactory();
factory.getShape("rectangle").draw()

This being much simpler and efficient enough. Besides, if the constructor of the ShapeFactory class has argument, Supplier will not work and we will have to use Function or other methods.

So why use the Supplier like this in this precise case ?

Alex Shesterov :

In the example above, it makes no sense to complicate things with the supplier. A simple constructor call is even easier to read (and is likely to be faster). Probably, the author of this examle intended to demonstrate how a Supplier can be invoked.

Suppliers become useful when you need to extract the retrieval (which is not necessarily creation) of an object, kind of "strategy pattern". E.g.:

public void drawRectangle(final Supplier<ShapeFactory> factorySupplier) {
    final ShapeFactory factory = factorySupplier.get();
    factory.getShape("rectangle").draw();
}

Then, you could call your method like this, and it would create a new factory:

drawRectangle(ShapeFactory::new); 

or for example like this:

@Autowired
private ShapeFactory shapeFactoryBean;
...
drawRectangle(() -> shapeFactoryBean); 

and it would use an existing factory instead of creating a new one.


Of course, the method from my example could just take a ShapeFactory as an argument. But one could imagine a situation that, for example, the factory only needs to be accessed in certain situations, so there's no need to create a new factory for the method call, e.g.:

public void drawRectangleConditionally(final Supplier<ShapeFactory> factorySupplier) {
    if (something) {
        final ShapeFactory factory = factorySupplier.get();
        factory.getShape("rectangle").draw();
    }
}
...
drawRectangleConditionally(ShapeFactory::new); 
// the factory will only be created if it's really needed. 

Note that a supplier can be used multiple times, so another use of suppliers is to get a sequence of objects, e.g.:

public List<T> createList(final int n, final Supplier<T> listItemSupplier) {
    final List<T> result = new ArrayList<>(n);
    for (int i = 0; i < n; ++i) {
        result.add(listItemSupplier.get());
    }
    return result;
}
...
createList(5, MyObject::new); // creates a list of 5 MyObjects
createList(3, () -> "hello"); // creates a list of 3 "hello" strings
createList(10, Random::nextLong); // creates a list of 10 random longs

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=458749&siteId=1