Мне нужно сделать переменную доступной для всей программы на Java - PullRequest
5 голосов
/ 06 ноября 2011

Так что моя проблема заключается в следующем. У меня есть класс с именем Globals, который содержит все переменные, которые мне нужны во всей программе. Он отлично работает для таких вещей, как строки, целые числа и другие вещи, с которыми вы можете использовать операцию =. Например:

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

Где-то в проекте я обращаюсь к ним, используя эти:

Globals.globalInteger += 17;

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

Однако я пытаюсь сделать класс, который я написал, глобальным (UserProfiles.class). Этот класс не использует операцию =, следовательно, всегда null, когда я получаю к нему доступ откуда-то еще и получаю java.lang.nullPointerException. Например, если я сделаю это (newProfile(String) - это метод внутри UserProfiles.class):

Globals.globalUserProfile.newProfile(profileName);

Я получаю java.lang.NullPointerException. Как я могу сделать мою переменную UserProfile.class доступной для всего проекта? Заранее спасибо.

Ответы [ 4 ]

4 голосов
/ 06 ноября 2011

Напишите так называемый фабричный класс, который строит весь ваш проект за один шаг.

Пример:

// 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;
    }
}

Здесь у вас есть 3 класса и один класс конфигурации. Все они зависят от класса конфигурации, C зависит от B, а B зависит от A.

Как вы можете видеть, зависимости отражаются параметрами конструктора, что хорошо, потому что зависимости явные (это означает, что вы теперь, какие зависимости нужны, не слишком заглядывая в исходный код).

Но как вы строите этот граф объектов? Ну, используя фабричный класс (здесь это даже статическая фабрика):

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

Как видите, вы строите граф объектов снизу вверх. Все зависимости являются явными, и вы отделяете процесс построения от бизнес-логики.

То, что мы здесь сделали, - это внедрение зависимостей в конструктор, то есть мы передали зависимости, в которых нуждается каждый класс, через конструктор. А для создания необходимых объектов мы написали фабрику.

В конце концов, у нас есть легкие классы (здесь нет строительных работ), явные зависимости (которых у вас нет синглтона) и максимальная гибкость (фабрика может даже вернуть подкласс C).

EDIT

Еще одним преимуществом является то, что вы можете тестировать свои классы изолированно, так как вы можете легко насмехаться над параметрами (например, передавая подклассы параметров).

4 голосов
/ 06 ноября 2011
2 голосов
/ 06 ноября 2011

Вы можете создать экземпляр класса по умолчанию в своем классе Globals:

public static UserProfile globalUserProfile = new UserProfile();

или вы должны объявить фабричный метод внутри класса UserProfile.

0 голосов
/ 30 августа 2016

Здесь, как и в большинстве мест, я бы не использовал шаблон Singleton.Вместо этого вы должны привыкнуть использовать Dependency Injection - на английском языке передавать экземпляр «глобального класса» классу, который в этом нуждается.На практике это может быть выполнено с помощью , требующей, чтобы"глобальный класс" передавался в качестве аргумента при инициализации любого другого класса, который будет нуждаться в этом.

В недавнем проекте мне нужны игрокизнать, где были все Монстры, монстры, чтобы знать, где все игроки, и выстрелы, чтобы знать, где были все игроки и монстры.Я поместил все это в один класс "GameObjects" и требовал, чтобы игроки, монстры и выстрелы передавали экземпляр при инициализации.Для реализации требуется немного больше времени, чем для Singleton, но это означает, что глобальный класс не будет доступен в тех местах, которые вы не ожидаете или не хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...