ホーム技術情報Singletonのサブクラス化 検索 | 更新情報
ARROW アロー スリップオンマフラー サイレンサー素材:チタン/カーボンエンド仕様 (TiRSC.a) GLADIUS650 09-13Javaの入門書 | デザパタ本 著書

プロジェクトミュー ブレーキパッド B-SPEC リア用 マークII MX83 89.8~93.2 送料無料の激安価格出大放出

結城浩

Javaで SPIDI スピーディー レザーパンツ TEKER LEATHER パンツ SIZE:50 SWAGE-LINE スウェッジライン フロント ブレーキホースキット ホースの長さ:50mmロング ホースカラー:ブラックスモーク DRAGSTAR250(00-07)、Singletonのサブクラス化のコーディングを試みます。インスタンスの唯一性をどのように保証するかを考えましょう。

プロジェクトミュー ブレーキパッド B-SPEC リア用 マークII MX83 89.8~93.2 送料無料ブランド直営店

プロジェクトミュー ブレーキパッド B-SPEC リア用 マークII MX83 89.8~93.2 送料無料ブランド公式通販

Singletonパターンのサブクラス化に関連したJavaのサンプルコードを紹介します。

このページを作成するにあたっては、GoF本はもちろんのこと、 デザインパターン・メーリングリストでのメールのやりとりを参考にしました。 澤田聡司さん、小山さん、中野靖治さん、宮本さん、杉村貴士さん、出井秀行さん 【2018年製】 215/65R16 ヨコハマ ブルーアース RV-02 サマータイヤ ホイールセット 4本 YOKOHAMA BluEarth ジョーカーステア 16-6.5J 車種例 アルファード ベルファイア RVR エルグランド デュアリス、 その他のみなさんに感謝します。 特に、澤田さんから多くの情報と示唆をいただきました。感謝します。

(メモ:GoF本のSingletonのバリエーションに言及する必要あり。いつか加筆すること)

メモ:以下のソースではRuntimeExceptionを使用しています。 一般に [ホイール1本(単品)] VERTEC ONE / Longbeak (MBK) 16インチ×6.0J PCD:100 穴数:4 インセット:43、RuntimeExceptionの利用には注意が必要ですが、 このソースでRuntimeExceptionをthrowしている部分は「プログラマの誤り」に起因するところであり、 正しい用法のはずです。

(1) Singletonの基本形 ―― 唯一のインスタンスを作る

JavaでSingletonを作るときの典型的な方法は次の通りです。

例えば、次のようにします。 以下ではDisplayクラスをSingletonとして実現しています。 Displayクラスのインスタンスは唯一で、 Display.getInstance()という式で得ることができます。

class Display {
 private static Display _instance = new Display();
 private Display() {
 }
 public static Display getInstance() {
 return _instance;
 }
 public void display(String msg) {
 System.out.println("Display: " + msg);
 }
}
class Main {
 public static void main(String[] args) {
 Display obj1 = Display.getInstance();
 Display obj2 = Display.getInstance();
 if (obj1 == obj2) {
 System.out.println("obj1 == obj2");
 }
 obj1.display("Hello");
 }
}

実行結果は次の通りです。

obj1 == obj2
Display: Hello

ただし、上のようなコーディングだと、Displayのサブクラスを作れないという制約が生じます。 コンストラクタをprivateにしているため、 サブクラスを作ると、コンパイル時のエラーになってしまうからです。 かといってコンストラクタをpublicやprotectedにすると、 プログラマが誤ってnewする危険性が生じてしまいます。

次の節では、この制約を解消します。

(2) クラスごとに管理 ―― クラスごとに唯一のインスタンスを作る

前節の制約を解消する方法を考えてみましょう。

import java.util.HashMap;
class Display {
 private static HashMap _classnameToInstance = new HashMap();
 private static Object _lock = new Object();
 protected Display() {
 synchronized (_lock) {
 String classname = this.getClass().getName();
 if (_classnameToInstance.get(classname) != null) {
 throw new RuntimeException("Already created: " + classname);
 }
 _classnameToInstance.put(classname, this);
 }
 }
 public static Display getInstance(String classname) {
 synchronized (_lock) {
 Display obj = (Display)_classnameToInstance.get(classname);
 if (obj == null) {
 try {
 Class cls = Class.forName(classname);
 obj = (Display)cls.newInstance();
 } catch (ClassNotFoundException e) {
 throw new RuntimeException(classname + " is not found");
 } catch (IllegalAccessException e) {
 throw new RuntimeException(classname + " cannot be accessed.");
 } catch (InstantiationException e) {
 throw new RuntimeException(classname + " cannot be instantiated.");
 }
 }
 return obj;
 }
 }
 public void display(String msg) {
 System.out.println("Display: " + msg);
 }
}
class ScreenDisplay extends Display {
 public void display(String msg) {
 System.out.println("ScreenDisplay: " + msg);
 }
}
class HyperDisplay extends Display {
 public void display(String msg) {
 System.out.println("HyperDisplay: " + msg);
 }
}
class Main {
 public static void main(String[] args) {
 Display screen1 = Display.getInstance("ScreenDisplay");
 Display screen2 = Display.getInstance("ScreenDisplay");
 Display hyper1 = Display.getInstance("HyperDisplay");
 Display hyper2 = Display.getInstance("HyperDisplay");
 screen1.display("Hello");
 screen2.display("Hello");
 hyper1.display("Hello");
 hyper2.display("Hello");
 if (screen1 == screen2) {
 System.out.println("screen1 == screen2");
 }
 if (hyper1 == hyper2) {
 System.out.println("hyper1 == hyper2");
 }
 }
}

実行結果は次の通りです。

ScreenDisplay: Hello
ScreenDisplay: Hello
HyperDisplay: Hello
HyperDisplay: Hello
screen1 == screen2
hyper1 == hyper2

上のコーディングだと、 Displayクラス・ScreenDisplayクラス・HyperDisplayクラスのそれぞれにインスタンスが1個ずつ存在することになります (正確には0個の場合もありえます。例えば上記のMainクラスを実行したとき、Displayのインスタンスは0個です)。

次の節では、 「クラスごとにインスタンスを1個」確保するのではなく、 「クラス階層全体でインスタンスを1個」する方法を示します。

(3) 1個だけ管理 ―― クラス階層全体で唯一のインスタンスを作る

import java.util.HashMap;
class Display {
 private static Display _instance = null;
 private static Object _lock = new Object();
 protected Display() {
 synchronized (_lock) {
 if (_instance != null) {
 throw new RuntimeException("Already created: " + _instance.getClass().getName());
 }
 _instance = this;
 }
 }
 public static Display getInstance(String classname) throws ClassNotFoundException {
 synchronized (_lock) {
 Class cls = Class.forName(classname);
 if (_instance == null) {
 try {
 Display obj = (Display)cls.newInstance();
 // assert obj == _instance;
 } catch (IllegalAccessException e) {
 throw new RuntimeException(classname + " cannot be accessed.");
 } catch (InstantiationException e) {
 throw new RuntimeException(classname + " cannot be instantiated.");
 }
 } else if (!_instance.getClass().isAssignableFrom(cls)) {
 throw new ClassCastException(classname);
 }
 return _instance;
 }
 }
 public void display(String msg) {
 System.out.println("Display: " + msg);
 }
}
class ScreenDisplay extends Display {
 public void display(String msg) {
 System.out.println("ScreenDisplay: " + msg);
 }
}
class HyperDisplay extends Display {
 public void display(String msg) {
 System.out.println("HyperDisplay: " + msg);
 }
}
class Main {
 public static void main(String[] args) throws Exception {
 Display screen1 = Display.getInstance("ScreenDisplay");
 Display screen2 = Display.getInstance("ScreenDisplay");
 screen1.display("Hello");
 screen2.display("Hello");
 if (screen1 == screen2) {
 System.out.println("screen1 == screen2");
 }
 try {
 Display hyper = Display.getInstance("HyperDisplay");
 hyper.display("Hello");
 } catch (ClassCastException e) {
 System.out.println("ClassCastException (OK)");
 }
 }
}

実行結果は次の通りです。

ScreenDisplay: Hello
ScreenDisplay: Hello
screen1 == screen2
ClassCastException (OK)

プロジェクトミュー ブレーキパッド B-SPEC リア用 マークII MX83 89.8~93.2 送料無料は全てここで通販中!

他にもバリエーションがありますけれど、まずはここまで。

リンク

更新履歴

ぜひ、感想をお送りください

あなたのご意見・感想をお送りください。 あなたの一言が大きなはげみとなりますので、どんなことでもどうぞ。

あなたの名前: メール:
学年・職業など: 年齢: 男性女性
(上の情報は、いずれも未記入でかまいません)

お手数ですが、、以下の問いに答えてから送信してください(迷惑書き込み防止のため)。
今年は西暦何年ですか?

何かの理由でうまく送れない場合にはメールあてにお願いします。


(C) 2003 結城浩
http://www.hyuki.com/
http://www.hyuki.com/techinfo/singleton.html
リンクはご自由に。フィードバックはお気軽に。

SuperSportMirror(スーパースポーツミラー) BMW 5シリーズ ドアミラー M60ミラー ブラック/手動/右ハンドル車 BMW E39 5シリーズ豊かな人生のための四つの法則

{yahoojp}jpprem01-zenjp40-wl-zd-7236