2011-11-06 7 views
5

私の問題はこれです。プログラム全体に必要なすべての変数を含むクラスGlobalsがあります。これは、文字列、整数、および=の操作を使用できる他のもののようなものでうまく動作します。たとえば:しかし、私は(私は自分自身を書いたクラスがグローバルにしようとしています私はJavaでプログラム全体にアクセス可能な変数を作成する必要があります

Globals.globalInteger += 17;

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

どこかのプロジェクトで
public class Globals { 
    public static int globalInteger = 23; 
    public static String globalString = "Hello, dude."; 
    public static UserProfile globalUserProfile; 
} 

、私はこれらを使用してそれらにアクセスUserProfiles.class)。このクラスでは=操作は使用されないため、他の場所からアクセスすると常にnullとなり、java.lang.nullPointerExceptionと表示されます。たとえば、私は(newProfile(String)UserProfiles.class内部メソッドです)これを行う場合:

Globals.globalUserProfile.newProfile(profileName);

私は java.lang.NullPointerExceptionを取得します。 UserProfile.class変数をプロジェクト全体にアクセス可能にするにはどうすればよいですか?前もって感謝します。

+5

"Globals"(特に '+ = 17' * shudder *)のパターンは良いものではありません。 http://stackoverflow.com/questions/4646577/global-variables-in-javaを参照してください – Gray

+0

ああ、私は参照してください。私はJavaにはまだまだ慣れていないし、まだいくつかの基本について混乱している。私はそれを読むでしょう。ありがとう。 – alxcyl

+0

質問を編集して、これを実行したいと思って、世界中に保存する必要があると思われる値のいくつかの実際の例を挙げたら、あなたの目標を達成するためのより良い方法についてコメントすることができます。 – Gray

答えて

2

あなたはグローバルクラスで、デフォルトでは、あなたのクラスをインスタンス化することができます

public static UserProfile globalUserProfile = new UserProfile(); 

か、のUserProfileクラスの内部でファクトリメソッドを宣言する必要があります。

+1

私はglobalUserProfileがnullであるかどうかをチェックし、publicアクセス可能な変数を持つ代わりにインスタンスをインスタンス化するgetメソッドも提案します。 'getUserProfile(){return globalUserProfile!= null? globalUserProfile:(globalUserProfile =新しいUserProfile()); } ' – Patrick

4

プロジェクト全体をワンステップで構築する、いわゆるファクトリクラスを作成します。

例:ここでは

// 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つのクラスと1つのコンフィギュレーション・クラスを持っています。これらのすべてが構成クラスに依存しています。CはBに依存しており、BはAに依存しています。

このように、依存関係はコンストラクタパラメータに反映されます。ソースコードをあまり見ずに依存関係が必要になったとき)。

しかし、このオブジェクトグラフをどのように作成しますか?まあ、ファクトリクラスを使用して(ここでは、それもstaticファクトリです):

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

一つの更なる利点は、あなたが簡単に(例えばパラメータのサブクラスを渡すことによって)パラメータを模擬可能性として、単独であなたのクラスをテストすることが可能だということです。

0

ここでは、ほとんどの場所と同様に、私はシングルトンパターンを使用しないでください。代わりに、依存性注入を使用する習慣を習得する必要があります。英語では、 "グローバルクラス"のインスタンスをそれを必要とするクラスに渡します。実際には、これはによって実行され、を必要とする他のクラスを初期化する際に引数として渡される "グローバルクラス"を必要とします。

最近のプロジェクトでは、すべてのプレイヤーがどこにいるのかを知るためにモンスターが、プレイヤーとモンスターがどこにあるのかを知るためにショットが必要でした。私はこれらすべてを1つの "GameObjects"クラスに入れ、Players、Monsters、およびShotsに初期化時にインスタンスを渡すよう要求しました。シングルトンよりも実装に少し時間がかかりますが、それはあなたが期待していない場所や希望したくない場所でグローバルクラスにアクセスしないことを意味します。

関連する問題