1
public class DataFactory {

    class SYNOP implements IDataSources {}
    class WRF implements IDataSources {}

    public abstract class Factory {
        public abstract IDataSources CreateModel();
    }

    public class SYNOPFactory extends Factory {

        @Override
        public IDataSources CreateModel() {
            return new SYNOP();
        }
    }

    public class WRFFactory extends Factory {

        @Override
        public IDataSources CreateModel() {     
            return new WRF();
        }       
    }

    public static void main(String[] args) {

        Factory factory = new WRFFactory();

    }
}

And i got message error like this:

No enclosing instance of type DataFactory is accessible. Must qualify the allocation with an enclosing instance of type DataFactory (e.g. x.new A() where x is an instance of DataFactory).

What did i do wrong?

Regards

Ahmet Emre Kilinc
  • 5,489
  • 12
  • 30
  • 42
  • You are trying to instantiate an inner class which is not `static` from a `static` context. This won't work. You need to mark your nested classes `static` (or instantiate them using an instance of `DataFactory`). – bcsb1001 Nov 17 '17 at 19:36
  • 1
    Or better: Define each class in its own File as intended. – OH GOD SPIDERS Nov 17 '17 at 19:38

3 Answers3

2

SYNOPFactory and WRFFactory are declared as inner class of DataFactory.

It means that instances of them require a instance of DataFactory.
You could instantiate them for example as

Factory factory = new DataFactory().new WRFFactory();

But in fact, it makes not really sense to make them inner classes.
Why do you would need to couple so tightly instances of them with DataFactory ?

You should rather declare them in their own class file.
And extract also other classes in their own classes. Otherwise you would have the same problem.


Note that if you want to hide IDataSources implementations from client, you could declare subclasses of them as private class member of the factory subclass that creates instances of them :

public class SYNOPFactory extends Factory {

    private class SYNOP implements IDataSources {
    }

    @Override
    public IDataSources CreateModel() {
       return new SYNOP();
    }
}

public class WRFFactory extends Factory {

    private class WRF implements IDataSources {
    }

    @Override
    public IDataSources CreateModel() {
       return new WRF();
    }
}

In this way, this will compile fine as you program by interface :

Factory factory = new WRFFactory();
IDataSources dateSources = factory.CreateModel();

But this will not as now WRF is private to the WRFFactory class :

WRF wrf = new ...;

Note also that it is not required to create multiple instances of a factory.
And repeating the new DataFactory() idiom will finish by creating many factory instances.

A factory may create multiple instances of objects but why would you need to have multiple instances of a factory ?
A single one can create all objects you need.
So you should have a singleton instance of the factory.
To achieve it, you can use the singleton DP or the dependency injection (that is better).

Dependency injection requires a DI framework.
You don't seem to use it.
As workaround, in plain java, you could implement a eager Singleton (thanks Bill Pugh) such as :

public class WRFFactory extends Factory {

    private class WRF implements IDataSources {
    }

    private static WRFFactory instance = new WRFFactory();

    private WRFFactory(){
    }

    public static WRFFactory getInstance(){
       return instance;
    }
    @Override
    public IDataSources CreateModel() {
       return new WRF();
    }
}

Now, you can create your IDataSources instances in this way :

IDataSources datasources = WRFFactory.getInstance().CreateModel();
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • If I declare them in own classes, i can still use pattern factory? –  Nov 17 '17 at 19:41
  • Of course...... – davidxxx Nov 17 '17 at 19:43
  • Ok but now i am trying divide my factory to own classes, and i am doing this like that: SYNOPFactory in own file, and Factory(abstract class in other file), example public class SYNOPFactory extends Factory { @Override public IDataSources CreateModel() { return new SYNOP(); } } I get error like this No enclosing instance of type DataFactory is available due to some intermediate constructor invocation –  Nov 17 '17 at 19:48
  • "You should rather declare them in their own class file. And extract also other classes in their own classes. Otherwise you would have the same problem." – davidxxx Nov 17 '17 at 19:53
1

Ok, so i am doing this like that:

File IDataSources.java

package pl.weatherPrediction.interfaces;

public interface IDataSources {
    //void getFiles(String url, String folder, String timeStamp);
}

File Factory.java

package pl.weatherPrediction.factory;

import pl.weatherPrediction.interfaces.*;

public abstract class Factory {
    public abstract IDataSources CreateModel();
}

File SYNOPFactory.java

package pl.weatherPrediction.factory;

import pl.weatherPrediction.factory.Factory;
import pl.weatherPrediction.interfaces.IDataSources;

public class SYNOPFactory extends Factory {

class SYNOP implements IDataSources {}

@Override
public IDataSources CreateModel() {
    return new SYNOP();
}

}

File WRFFactory.java

package pl.weatherPrediction.factory;

import pl.weatherPrediction.interfaces.IDataSources;

public class WRFFactory extends Factory {

    class WRF implements IDataSources {}

    @Override
    public IDataSources CreateModel() {     
        return new WRF();
    }       
}

File Main.java

package pl.weatherPrediction.App;

import pl.weatherPrediction.factory.*;

public class Main {

    public static void main(String[] args) {

        Factory factory = new SYNOPFactory();
        factory.CreateModel();

        factory = new WRFFactory();
        factory.CreateModel();

    }
}

Is that correct @davidxxx?

  • 1
    It is rather fine. Just the way of instantiating factory subclasses should be improved. I updated my answer to explain this point. – davidxxx Nov 17 '17 at 20:08
  • Yes, yes i am reading your hints now @davidxxx :) –  Nov 17 '17 at 20:12
  • I updated with a simple and efficient singleton implementation. But note that in "real" projects, a dependency injection facility should be favored over this classical implementation. – davidxxx Nov 17 '17 at 20:14
  • Ok so your implementation for singleton in this case will be better than this? –  Nov 17 '17 at 20:52
  • 1
    The singleton will be more simple (not need to handle himself the singleton instantiation/retrieval) and more flexible. See SpringFramework for example : https://projects.spring.io/spring-framework/ – davidxxx Nov 18 '17 at 13:24
0

You need the object

private static DataFactory dataFactory;

You need a private Constructor

    private DataFactory() {
}

And you need an instance builder

    public static DataFactory getInstance() {

    if (DataFactory.dataFactory == null) {
        DataFactory.dataFactory = new DataFactory();

    }

    return DataFactory.dataFactory;

}

Then you call it in main

DataFactory dataFactory = DataFactory.getInstance();

This is a true factory Class

SynchroDynamic
  • 386
  • 2
  • 14