2011-01-28 3 views
5

私はActionscript3の背景から来て、これは初めての私の人生でJavaを書くことです。ハッシュテーブルはFlashの辞書と似ているようですが、正しく使用していますか?私は、Hashtableは文字列をキーとして受け入れ、Typefaceはオブジェクトとして受け入れると考えています。これは正しいです?このようなものに適している別のCollectionサブクラスはありますか?是非、n00b Javaを裂けてください。私はこれを学ぶ必要があります。Hashtableは資産を格納するのに適していますか?

package com.typeoneerror.apps.app_name.utils; 

import android.content.Context; 
import android.graphics.Typeface; 

import java.util.Hashtable; 

public class FontRegistry 
{ 
    private static FontRegistry _instance; 

    private Context       _context; 
    private Hashtable<String, Typeface>  _fonts; 

    private FontRegistry() 
    { 
     _fonts = new Hashtable<String, Typeface>(); 
    } 

    public static FontRegistry getInstance() 
    { 
     if (_instance == null) 
     { 
      _instance = new FontRegistry(); 
     } 
     return _instance; 
    } 

    public void init(Context context) 
    { 
     _context = context; 

    } 

    public Typeface getTypeface(int resourceId) 
    { 
     String fontName = _context.getResources().getString(resourceId); 
     if (!_fonts.containsKey(fontName)) 
     { 
      String fontPath = "fonts/" + fontName; 
      Typeface typeface = Typeface.createFromAsset(_context.getAssets(), fontPath); 
      _fonts.put(fontName, typeface); 
     } 
     return (Typeface)_fonts.get(fontName); 
    } 
} 
+2

rfeakが言ったことを除いて、それは問題ありません。いくつかのヒント:アンダースコアを除外(してください)すると、 'this.context = context'が必要です。 'private final Map fonts = new HashMap ()'のようなフォントを初期化することができます。並行性がある場合は、あなたの怠惰なシングルトンに問題が発生する可能性があります。警告をオンにすると、あなたの最後のキャストは必ず不要です。 – maaartinus

+1

このクラスへのアクセスはシングルスレッドでもマルチスレッドでもかまいませんか?私は 'getInstance()'のあなたの現在の実装がスレッドセーフではないので尋ねます。 –

+0

@ dave.c私は分かりません。私が言ったように、これは私の初めてのJavaを書くので、答えとしての任意のアドバイスは非常に高く評価されるだろう。 – typeoneerror

答えて

7

2つの提案があります。

まず、変数型はMapのインターフェイスを参照する必要があります。これにより、将来の柔軟性が増し、他のほとんどのJava開発者とのメッシュ・メッシュ化が進んでいきます。

第2に、実装はHashTableではなく、HashMapでなければなりません。 HashTableはすべてを同期しますが、HashMapではそうではありません。

マルチスレッドアクセスが必要な場合は、HashTableの代わりにConcurrentHashMapを使用することをお勧めします。 ConcurrentHashMapは、アクセス中にマップ全体をロックしないため、パフォーマンスが向上します。

ので、

private Map<String, Typeface>  _fonts; 

_fonts = new HashMap<String, Typeface>(); 

最後に、多くのJava開発者は、あなたがアンダースコアでメンバ変数を開始しないことを好むだろう。これは議論の余地があります。

EDIT:最後のニックピック。レジストリにシングルトンパターンを使用しているようです。これは後であなたを噛むことができるので、シングルトンを避けることを検討してくださいhttp://accu.org/index.php/journals/337。しかし、それを無視して、宣言でシングルトンの静的インスタンスをインスタンス化する方が良いかもしれません。これは、初めてフェッチするときに起こりうる競合を回避できます。だから、

private static FontRegistry _instance = new FontRegistry; 
+0

素晴らしい回答、ありがとうございます。私はシングルトンパターンのファンでもありません。おそらくリファクタリングするだろう。 – typeoneerror

+1

'Context'を'静的 'メンバーとして持つシングルトンパターンは、' Context'がガベージコレクションされることから渡された 'Activity'を防ぐことができるので、Androidでは危険です。 –

1

私のコメントに展開するには、getInstance()の実装はスレッドセーフではありません。

public class Singleton { 

    // Private constructor prevents instantiation from other classes 
    private Singleton() { 
    } 

    /** 
    * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
    * or the first access to SingletonHolder.INSTANCE, not before. 
    */ 
    private static class SingletonHolder { 
     public static final Singleton INSTANCE = new Singleton(); 
    } 

    public static Singleton getInstance() { 
     return SingletonHolder.INSTANCE; 
    } 
} 

。また、あなたがAndroidのないように、「漏れのために開発するときに注意する必要があります:あなたは本当にシングルトンパターンを使用する必要がある場合、あなたは(私は露骨にwikipedia articleからコピーした)「ビル・ピュー」バージョンを使用することができます"a Context。なぜそれが悪いのか、それを避ける方法については、good articleです。要するに、Context(またはContextを参照するオブジェクト)へのstaticの参照は、Activityインスタンスがガベージコレクションできないことを意味します。

+0

これを書いてくれてありがとう、dave。 – typeoneerror

+0

すばらしいリンク。私はイニシャライザのアプリケーションコンテキストを使用していることに注意してください:FontRegistry.getInstance()。init(getApplicationContext()); 。記事では「...アプリケーションコンテキスト。このコンテキストは、アプリケーションが生存していて、アクティビティライフサイクルに依存しない限り生き続ける」と指定しています。 – typeoneerror

+0

うれしいことがわかりました。あなたが述べるように、 'getApplicationContext()'を使うことは問題を回避する方法です。 –

関連する問題