Androidアプリで、一度だけ作成してどこでも使えることが求められるオブジェクトには、Singletonパターンを用います。 シングルトンパターンは、クラスのインスタンスを「1つ」だけに制限するソフトウェアのデザインパターンです。 そこで、プロジェクトやソフトウェアにSingletonパターンを実装するために、シングルトンクラスを作成する。 このブログでは、Kotlinでシングルトンクラスを作る方法?
Singleton Class
シングルトンクラスとは、クラスのインスタンスを1つだけ作成し、どこでも使用できるように定義されたクラスです。
ネットワークサービスやデータベースサービスなど、クラスのインスタンスが1つだけ必要なときに使用されます。
Properties of Singleton Class
Following are the properties of a typical singleton class:
- Only one instance.これは、シングルトン・クラスの典型的な特性です。 シングルトン・クラスは1つのインスタンスしか持たず、これはクラス内で、クラスのインスタンスを提供することによって行われる。 また、外部のクラスやサブクラスがインスタンスを生成できないようにする必要がある。
- グローバルにアクセス可能。 シングルトンクラスのインスタンスは、各クラスが利用できるようにグローバルにアクセス可能であるべきである。
クラスをSingletonにするためのルール
Singletonクラスを作るには、以下のルールに従わなければならない。
- A private constructor
- A static reference of its class
- One static method
- Globally accessible object reference
- Consistency across multiple threads
Singleton Example
java で Singleton class の例として、下記のものが挙げられます。
public class Singleton { private static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; }}
スレッドの干渉がないようにインスタンスを作成するとき、synchronizedキーワードを使用します。
同じことをKotlinのコードで見てみましょう。
object Singleton
さて、この後どうするのでしょう?
何もしません!
この後どうするのでしょう? 冗談でしょう? いいえ、これがKotlinでSingletonクラスを使用するためのコードです。 とても簡単でしょう?
KotlinでSingletonクラスを使うには、objectキーワードを使う必要があるんだ。 オブジェクトクラスは、関数、プロパティ、およびinitメソッドを持つことができます。 オブジェクトにはコンストラクタは使えないので、初期化が必要な場合はinitメソッドを使い、クラス内にオブジェクトを定義することができます。
object Singleton{ init { println("Singleton class invoked.") } var variableName = "I am Var" fun printVarName(){ println(variableName) }}fun main(args: Array<String>) { Singleton.printVarName() Singleton.variableName = "New Name" var a = A()}class A { init { println("Class init method. Singleton variableName property : ${Singleton.variableName}") Singleton.printVarName() }}
ここで、Kotlinのシングルトンクラスの例を見てみましょう。 クラスがインスタンス化されると、そのオブジェクトクラスに変更が反映されることがあります。 つまり、上記のコードの出力は次のようになります:
Singleton class invoked.I am VarClass init method. Singleton variableName property : New NameNew Name
Object extending a class
Kotlinのオブジェクトは、通常のクラスと同様に、あるクラスを拡張したり、あるインターフェースを実装するために使用することができます。
fun main(args: Array<String>) { var a = A() Singleton.printVarName()}open class A { open fun printVarName() { print("I am in class printVarName") } init { println("I am in init of A") }}object Singleton : A() { init { println("Singleton class invoked.") } var variableName = "I am Var" override fun printVarName() { println(variableName) }}
そして、上記のコードの出力は次のようになります:
I am in init of AI am in init of ASingleton class invoked.I am var
つまり、ほとんどの場合、通常のクラスと同じようにオブジェクトクラスを使用することができるのです。
次回の面接のために、ここからシステム設計を学びましょう!
Kotlinで引数を使ったシングルトンクラス
前回のブログで、シングルトンクラスにはコンストラクタがないことを学びました。 何かを初期化する場合は、シングルトンクラスでinitを使うことで初期化することができます。 しかし、パラメータ化されたコンストラクタのように、初期化のために何らかの引数を渡す必要がある場合はどうでしょうか。 ここではコンストラクタを使うことができない。
Android について特に説明すると、Android では一般に、シングルトンの init ブロックにコンテキスト インスタンスを渡す必要があることを私たちは知っています。 これは、早期初期化と遅延初期化を使用して行うことができます。 早期初期化では、すべてのコンポーネントは Application.onCreate() の中で init() 関数を用いて初期化されます。 しかし、これはメインスレッドをブロックすることによって、アプリケーションの起動を遅くする結果になります。 そのため、一般的には遅延初期化の方法を使用することをお勧めします。 遅延初期化では、シングルトンのインスタンスを返す関数の引数としてコンテキストを使用します。 これを実現するには、SingletonHolder クラスを使用します。
open class SingletonHolder<out T: Any, in A>(creator: (A) -> T) { private var creator: ((A) -> T)? = creator @Volatile private var instance: T? = null fun getInstance(arg: A): T { val checkInstance = instance if (checkInstance != null) { return checkInstance } return synchronized(this) { val checkInstanceAgain = instance if (checkInstanceAgain != null) { checkInstanceAgain } else { val created = creator!!(arg) instance = created creator = null created } } }}
上記のコードは、ダブルチェックロック方式で最も効率的なコードで、Kotlin の lazy() 関数とどこか似ているため、遅延初期化と呼ばれるようになったのです。
ここで、上記のコードでは、SingletonHolder に引数として渡される creator 関数の代わりに、カスタムラムダをインラインで宣言したり、シングルトン クラスの private コンストラクターへの参照を渡すことができます。
class YourManager private constructor(context: Context) { init { // do something with context } companion object : SingletonHolder<YourManager, Context>(::YourManager)}
さて、以下のコードを書くと、シングルトンは簡単に呼び出すことができ、初期化もできます。 このブログが気に入っていただけたら幸いです。 また、Kotlinのサイトも参照してください。 Androidのクールなトピックについてもっと知りたい方は、私たちのブログサイトを訪問して、私たちの学習の旅に参加してください。