alxcyl
alxcyl

Reputation: 2722

I need to make a variable accessible to the whole program in Java

So my problem is this. I have a class called Globals that contains all the variables I need all over the program. It works fine for things like strings, integers and other things that you can use the = operation on. For example:

public class Globals {
   public static int globalInteger = 23;
   public static String globalString = "Hello, dude.";
   public static UserProfile globalUserProfile;
}

Somewhere in the project, I access them using these:

Globals.globalInteger += 17;

Globals.globalString = "Why, hello there!";

However, I am trying to make a class that I wrote myself global (UserProfiles.class). This class does not use the = operation, hence, it is always null when I access it from somewhere else and I get java.lang.nullPointerException. For example if I do this (newProfile(String) is a method inside UserProfiles.class):

Globals.globalUserProfile.newProfile(profileName);

I get java.lang.NullPointerException. How can I make my UserProfile.class variable accessible all throughout the project? Thanks in advance.

Upvotes: 5

Views: 28956

Answers (3)

helpermethod
helpermethod

Reputation: 62294

Write a so called factory class which builds your whole project in one step.

Example:

// a class which store configuration parameters - must be instanstiable!
public class Configuration {
   public Configuration() {
       // get configuration from Properties file, Resource Bundle etc.
   } 
}

public class A {
    private Configuration configuration;

    public A(Configuration configuration) {
        this.configuration = configuration;
    }
}

public class B {
    private Configuration configuration;
    private A a;

    public B(A a, Configuration configuration) {
        this.a = a;
        this.configuration = configuration;
    }
}

public class C {
    private Configuration configuration;
    private B b;

    public C(B b, Configuration configuration) {
        this.b = b;
        this.configuration = configuration;
    }
}

Here you have 3 classes and one configuration class. All of them are dependent on the configuration class, C is dependent on B and B is dependent on A.

As you can see, the dependencies are reflected by the constructor parameters, which is good because dependencies are explicit (that means, you now which dependencies are needed without having too look at the source code).

But, how do you build this object graph? Well, by using a factory class (here, it's even a static factory):

public class ApplicationFactory {
    // prevents instantiation
    private ApplicationFactory() {};

    public static C buildApplicationGraph() {
        // first, build the leaf objects (objects without other dependencies), here
        // Configuration
        Configuration configuration = new Configuration();

        // now, start injecting the dependencies needed
        // a only need a Configuration object
        A a = new A(configuration);

        // B needs a Configuration and an A object
        B b = new B(a, configuration);

        // we're done here        
        return new C(b, configuration);         
    }
}

As you can see, you are building the object graph bottom up. All dependencies are explicit, and you are seperating the construction process from the business logic.

What we have done here is constructor dependency injection, i.e. we passed in the dependencies every class needs via the constructor. And for creating the objects needed, we wrote a factory.

In the end, we have lightweight classes (no construction work here), explicit dependencies (which you don't have using a Singleton), and maximum flexibility (the factory could even return a subclass of C).

EDIT

One further advantage is that you're able to test you classes in isolation, as you could easily mock the parameters (e.g. by passing in subclasses of the parameters).

Upvotes: 5

aleroot
aleroot

Reputation: 72676

You can instantiate your class by default in your Globals class :

public static UserProfile globalUserProfile = new UserProfile();

or you have to declare a factory method inside of UserProfile class.

Upvotes: 2

Related Questions