-2

Please notice the updates, my question was not clearly formulated. Sorry for that.

Let us assume we have the following code:

class Foo extends/implements AnAbstractClass/AnInterface { /* to make sure the constructor with int as input is implemented */ 
    Foo(int magicInt) { magicInt + 1; /* do some fancy calculations */ }
}

class Bar extends/implements AnAbstractClass/AnInterface { /* to make sure the constructor with int as input is implemented */ 
    Bar(int magicInt) { magicInt + 2; /* do some fancy calculations */ }
}

class Factory<T extends/implements AnAbstractClass/AnInterface> {
    int magicInt = 0; 

    T createNewObject() {
        return new T(magicInt) // obviously, this is not working (*), see below
    }
}

/* how it should work */
Factory<Foo> factory = new Factory<Foo>();
factory.createNewObject() // => Foo with magicInt = 1

Factory<Bar> factory = new Factory<Bar>();
factory.createNewObject() // => Bar with magicInt = 2

At position (*) I don't know what to do. How can I make sure, that the constructor with a signature like this ...(int magicInt) is implemented? I cannot define

  1. a constructor with a certain signature in an interface

    interface AnInterface {
        AnInterface(int magicInt);
    }
    
  2. an abstract class enforcing a certain constructor

    abstract class AnAbstractClass {
        abstract AnAbstractClass(int magicInt);
    }
    

    and this is obviously missing the requirement of an implemented constructor in the subclasses:

    abstract class AnAbstractClass {
       AnAbstractClass(int magicInt) {}
    }
    
  3. a static method within an interface or abstract class, which can be overridden for each implementation of AnInterface or AnAbstractClass (I think of a factory pattern)

What is the way to go?

Community
  • 1
  • 1
Michael Dorner
  • 11,986
  • 10
  • 64
  • 95
  • I don't understand what your question is... What exactly are you trying to achieve and why doesn't it work? – Cedric Reichenbach Nov 02 '15 at 10:48
  • 1
    I think there is something odd in your desired result code. `SampleSource` has parameter that extends `SampleFactory`. Then in `getCurrentSample()` you call on this sample factory to create a sample which should have the same type as the `SampleFactory`. So creating a sample gives you a sample factory? – Timo Nov 02 '15 at 10:49
  • 1
    Well since Java 8 static methods are allowed in interfaces. – Flown Nov 02 '15 at 10:49
  • 1
    Seems weird to have classes that both extend `Sample` and implement `SampleFactory`... – Thomas Nov 02 '15 at 10:49
  • 1
    @Flown he does not want static method in interface, he wants use interface to enforce class which implements that interface to has one. – user902383 Nov 02 '15 at 10:50
  • How logical is it that you have something that is also its own factory? It looks like there is something amiss in your OO design. – Erwin Bolwidt Nov 02 '15 at 10:55
  • I thought it is kind of ugly to have an object to create other objects. But I am open to all ideas. – Michael Dorner Nov 02 '15 at 10:55
  • You thought it is ugly, but you still chose to implement the [Factory Pattern](http://www.oodesign.com/factory-pattern.html), which is *explicitly* that? Curious. – Andreas Nov 02 '15 at 10:57
  • No, you cannot have *constructors* in an interface. The constructor is called when an object instance is created by the `new` operator, and you cannot instantiate an interface. – Andreas Nov 02 '15 at 11:01
  • 3
    Because of type-erasure, the actual type of `T` is unknown at runtime, so `T.class` won't work. – Andreas Nov 02 '15 at 11:04
  • @Andreas Re „_you cannot instantiate an interface_“: Well, with [anonymous classes](http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html) you can. – Gerold Broser Nov 02 '15 at 11:09
  • @GeroldBroser That's not instantiating an interface. That's defining a new unnamed class implementing the interface and instantiating the (anonymous) class, all in one. The link you gave even says so: *"They enable you to declare and instantiate a class at the same time."* – Andreas Nov 02 '15 at 11:13
  • Thanks for all your input. I see the problem that the question was not very well formulated. I tried to improve the question itself. – Michael Dorner Nov 02 '15 at 14:47
  • I've adapted my answer to the new version of your question. – Thomas Nov 03 '15 at 09:34
  • Actually it would be interesting, why there are so many down votes... :-/ – Michael Dorner Nov 06 '15 at 12:06
  • 1
    It seems to me that if you have to think this hard to come up with a "fancy" or "clever" solution, then the solution is likely to be fragile or difficult to maintain. Surely there is a better decomposition for your problem that would enable the use of already well-established, proven patterns. – scottb Nov 07 '15 at 08:24

3 Answers3

4

I really don't see your idea working.

I feel it breaks the concept of the Factory pattern, which really aims at having a method responsible for creating instances of a single class see ref.

I would rather:

  1. have one method in your factory class for each type of object you want to construct
  2. and possibly instead of having the specific behaviour in constructors, have one common constructor in a parent abstract class and one abstract method that does the fancy computation (but that's really style preference).

Which would result in something along the lines of:

abstract class AbstractSample {
    private int magicInt;

    public AbstractSample(int magicInt) {
        this.magicInt = magicInt;
    }

    protected int getMagicInt() {
        return magicInt;
    }

    public abstract int fancyComputation();

}

public class Foo extends AbstractSample {
    public Foo(int magicInt) {
        super(magicInt)
    }

    public int fancyComputation() {
        return getMagicInt() + 1;
    }
}

public class Bar extends AbstractSample {
    public Bar(int magicInt) {
        super(magicInt)
    }

    public int fancyComputation() {
        return getMagicInt() + 2;
    }
}

public class SampleFactory {
    private int magicInt = 0;

    public Foo createNewFoo() {
        return new Foo(magicInt);
    }

    public Bar createNewBar() {
        return new Bar(magicInt);
    }
}

Answer to the previous version of the question might be deleted if the updated answer satisfies the OP

It's definitely weird to have classes that both extend Sample and implement SampleFactory...

I would rather have something along the lines of:

class Sample { 
    protected Sample() { /* ... */ }
}

interface SampleFactory<T extends Sample> {
    T createSample(final int i);
}

class AccelerationSample extends Sample {
    public AccelerationSample(final int i) { /* do some fancy int calculations*/ }
}

class OrientationSample extends Sample {
    private OrientationSample (final int i) { /* do some fancy int calculations*/ }
}

abstract class SampleSource<T extends Sample> {
    int magicInt; 
    SampleFactory<T> sampleFactory;
    T getCurrentSample() {
       return sampleFactory.createSample(magicInt);
    }
}

class AccelerationSampleSource extends SampleSource<AccelerationSample> {
    SampleFactory<AccelerationSample> sampleFactory = new SampleFactory<> {
       public AccelerationSample createSample(final int i) {
          return new AccelerationSample(i);
       }
    }
}

class OrientationSampleSource extends SampleSource<OrientationSample> {
    SampleFactory<OrientationSample> sampleFactory = new SampleFactory<> {
       public OrientationSample createSample(final int i) {
          return new OrientationSample(i);
       }
    }
}

It would be cleaner still to use named factories, such as

public AccelerationSampleFactory implements SampleFactory<AccelerationSample> {
    public AccelerationSample createSample(final int i) {
        return new AccelerationSample(i);
    }
 }

Which you could then use as

class AccelerationSampleSource extends SampleSource<AccelerationSample> {
    SampleFactory<AccelerationSample> sampleFactory = new AccelerationSampleFactory();
}   
Thomas
  • 685
  • 5
  • 13
  • Indeed, sorry... Can't define static methods in an interface... I've updated my answer accordingly. (No need for the method to be static, if you want it to be generic). – Thomas Nov 02 '15 at 11:06
  • 1
    (to be more specific, in java 8, you CAN have static methods in interfaces, but definitely not static methods returning an instance type) – Thomas Nov 03 '15 at 09:37
  • Thanks for your solution, but then I have a static factory method for each class (in my case I would have dozens of such). I thought therefore generics were introduced. :) – Michael Dorner Nov 05 '15 at 08:44
  • Moreover there is no polymorphism anymore with your solution. – Michael Dorner Nov 05 '15 at 08:47
  • 1
    Indeed, that's what I mentioned in introduction. The Factory pattern usually aims at having a factory method *per class*. There is some polymorphism, in the form of method overriding. Generics are useful in many contexts, but the Factory pattern just isn't one of them IMHO. You could, however, use introspection to call the constructor in your factory, but I don't like that solution much. – Thomas Nov 05 '15 at 10:36
2

As you have noted, none of the 3 ideas in the question are supported (a constructor with a certain signature in an interface, an abstract class enforcing a certain constructor, or a static method within an interface or abstract class)

However, you can define an interface (or abstract class) that is a Factory for the type that you ultimately want.

public interface AnInterface {
    int fancyComputation();
}
public interface IFooBarFactory<T extends AnInterface> {
    T create(int magicNumber);
}

IFooBarFactory has 2 concrete implementations

public class BarFactory implements IFooBarFactory<Bar> {
    public Bar create(int magicNumber) {
        return new Bar(magicNumber);
    }
}
public class FooFactory implements IFooBarFactory<Foo> {
    public Foo create(int magicNumber) {
        return new Foo(magicNumber);
    }
}

Then use the strategy pattern (https://en.wikipedia.org/wiki/Strategy_pattern) to retrieve the correct factory. Then use this factory, which has a known interface, to manufacture your object with the correct value (and any additional values that are required to manufacture an object).

    FooBarFactory fooBarFactory = new FooBarFactory();
    IFooBarFactory<T> factory = fooBarFactory.createFactory(typeOfAnInterface);
    T impl = factory.create(magicNumber);

With the conrete implementations

public class Bar implements AnInterface {
    private final int magicInt;
    public Bar(int magicInt) {
        this.magicInt = magicInt;
    }
    public int fancyComputation() {
        return magicInt + 2;
    }
}
public class Foo implements AnInterface {
    private final int magicInt;
    public Foo(int magicInt) {
        this.magicInt = magicInt;
    }
    public int fancyComputation() {
        return magicInt + 1;
    }
}

the following code:

public static void main(String ... parameters) {
    test(Foo.class);
    test(Bar.class);
}
private static <T extends AnInterface> void test(Class<T> typeOfAnInterface) {
    T impl = createImplForAnInterface(typeOfAnInterface, 10);
    System.out.println(typeOfAnInterface.getName() + " produced " + impl.fancyComputation());
}
private static <T extends AnInterface> T createImplForAnInterface(Class<T> typeOfAnInterface, int magicNumber) {
    FooBarFactory fooBarFactory = new FooBarFactory();
    IFooBarFactory<T> factory = fooBarFactory.createFactory(typeOfAnInterface);
    T impl = factory.create(magicNumber);
    return impl;
}

prints

Foo produced 11
Bar produced 12

This provides a number of benefits over a solution with introspection or static factories. The caller does not need to know how to manufacture any of the objects, nor is the caller required to know or care when method is the "correct" method to use in order to retrieve the correct type. All callers simply call the one public/known component, which returns the "correct" factory. This makes your callers cleaner because they are no longer tightly coupled to the concrete implementations of AnInterface for the types FooBar. They only need to be concerned with "I need an implementation of AnInterface, which consumes (or processes) this type." I know that this means you have two "factory" classes. One to retrieve the correct factory, and the other which is actually responsible for creating the concrete types Foo and Bar. However, you hide this implementation detail from the callers through an additional layer of abstraction (see the createImplForAnInterface method).

This approach will be particularly beneficial if you are generally using some form of dependency injection. My recommendation with correspond exactly to Guice's assisted inject (https://github.com/google/guice/wiki/AssistedInject) or a similar idea in Spring (Is it possible and how to do Assisted Injection in Spring?).

This means that you need to have several factory classes (or dependency injection binding rules for Guice) but each of these classes are small, simple, and easy to maintain. Then you write a small test that retrieves all classes that implement AnInterface and you verify that your component which implements the strategy-pattern has covered all cases (through reflection - I would use the Reflections class in org.reflections:reflections). This gives you a usable code-abstraction that simplifies the use of these objects by reducing redundant code, loosening a tight coupling of components, and not sacrificing polymorphism.

Community
  • 1
  • 1
Nathan
  • 1,437
  • 8
  • 18
2

It sounds like you're really looking for a solution to how to write a generic factory method without a bunch of if/else blocks and without writing one in each class. As such, consider using reflection as in the following code:

interface Interface {
}

class Foo implements Interface {
    Foo(int magicInt) { magicInt = magicInt + 1; /* do some fancy calculations */ }
}

class Bar implements Interface {
    Bar(int magicInt) { magicInt = magicInt + 2; /* do some fancy calculations */ }
}

class Factory<T extends Interface> {
    int magicInt = 0; 

    public T createNewObject(Class<T> typeToMake) {
        try {
            T t = createNewObjectWithReflection(typeToMake);
            return t;
        } catch (Exception e) {
            throw new RuntimeException("Construction failed!", e);
        }
    }

    private T createNewObjectWithReflection(Class<T> typeToMake) throws Exception {
        // find the constructor of type to make with a single int argument
        Constructor<T> magicIntConstructor = typeToMake.getDeclaredConstructor(Integer.TYPE);
        // call the constructor with the value of magicInt
        T t = magicIntConstructor.newInstance(magicInt);
        return t;
    }
}

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        Factory<Foo> fooFactory = new Factory<Foo>();
        Foo foo = fooFactory.createNewObject(Foo.class);
        System.out.println(foo);

        Factory<Bar> barFactory = new Factory<Bar>();
        Bar bar = barFactory.createNewObject(Bar.class);
        System.out.println(bar);
    }
}

You can run the demo at IDEOne here.

entpnerd
  • 8,063
  • 5
  • 36
  • 60
  • Yes this is the kind of solution I am looking for. But is it that ugly in Java? – Michael Dorner Nov 07 '15 at 07:44
  • Pretty much, yes. I edited the code post to tidy up the code, a bit, but reflection in general isn't often pretty. – entpnerd Nov 07 '15 at 08:16
  • There is no reason for the factory itself to be generic. It would be sufficient to have the method in the factory generic. I also think that you could probably achieve the same functionality using TypeLiteral with a Factory binding for Guice using assisted-inject. That makes your code a bit cleaner. – Nathan Nov 07 '15 at 10:27
  • 1
    But pretty much regardless of what solution you go with, you are going to want some kind on automated reflections test to ensure that you have covered all of your use-cases. Otherwise it is possible to create a new sub-class that doesn't conform to what your factory expects/requires, and then you crash. One of the serious limitations, of this approach, however, is that it does not work anymore, if Foo or Bar require different parameters in their constructor. If Foo requires a DB connection but Bar requres a WS client, then the constructors will differ, and this approach is no longer viable. – Nathan Nov 07 '15 at 11:15
  • Thanks for your comments Nathan. Fair comment about the factory class, itself, not needing to be generic - I just tried to make all the classes conform as closely as possible to the original factory class in the question. I considered using TypeLiteral, but it seemed like the only feasible way to obtain get the type information back was to pass TypeLiteral into the factory method in lieu of a class. Since the problem was about instantiating a new class, passing a class seemed simpler because if I pass in a TypeLiteral, I'm just using that to get back a class object for invoking a constructor. – entpnerd Nov 07 '15 at 17:48
  • Your solution becomes even simpler if we do away with the paramter in the constructor at all. If we define an initializeMagicNumber(int) method in the Abstract class/Interface, then we can just call "getInstance" on the class in order to instantiate a new object using the default constructor. Once we have an object, we can initialize it in the factory. That, of course, leaves open the possibility that someone will simply create a new object without initializing it properly, but it reduces the amount of code to write, assuming all impl's have no further dependencies. – Nathan Nov 07 '15 at 20:31
  • @MichaelDorner, thanks for the bounty. If you have any follow up questions, please don't hesitate to ask. :-) – entpnerd Nov 09 '15 at 13:34