ホーム技術情報Singletonのサブクラス化 検索 | 更新情報
【2017年製】 185/65R14 ダンロップ ウインターマックス02 WM02 スタッドレスタイヤ ホイールセット 4本 DUNLOP WINTERMAXX02 シュナイダー DR-01 14-5.5J 車種例 モビリオ エアウエィブJavaの入門書 | デザパタ本 著書

clazzio シートカバー クラッツィオ プライムタイプ ホンダ エリシオン 型式 RR1/RR2 RR3/RR4 年式 H16/5-H17/9 定員 8人 ≪ 運転席手動/助手席肘掛有/2列目肘掛3本仕様/ヘッドレスト総数8個車用 ≫※2列目回転機構付不可 ※サイドエアバック付車不可激旬アイテム続々入荷

結城浩

Javaで 【送料無料 ジムニー】 175/80R16 16インチ MLJ デイトナSS 5.5J 5.50-16 DUNLOP ダンロップ グラントレック PT3 サマータイヤ ホイール4本セット【DUsum18】 15インチアテンザセダンGG系WEDS レオニス VX ハイパーシルバーミラーカット 6.0Jx15ZIEX ZE914F 195/65R15、Singletonのサブクラス化のコーディングを試みます。インスタンスの唯一性をどのように保証するかを考えましょう。

clazzio シートカバー クラッツィオ プライムタイプ ホンダ エリシオン 型式 RR1/RR2 RR3/RR4 年式 H16/5-H17/9 定員 8人 ≪ 運転席手動/助手席肘掛有/2列目肘掛3本仕様/ヘッドレスト総数8個車用 ≫※2列目回転機構付不可 ※サイドエアバック付車不可大バーゲン!

clazzio シートカバー クラッツィオ プライムタイプ ホンダ エリシオン 型式 RR1/RR2 RR3/RR4 年式 H16/5-H17/9 定員 8人 ≪ 運転席手動/助手席肘掛有/2列目肘掛3本仕様/ヘッドレスト総数8個車用 ≫※2列目回転機構付不可 ※サイドエアバック付車不可【半額以下!送料無料で】

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

このページを作成するにあたっては、GoF本はもちろんのこと、 デザインパターン・メーリングリストでのメールのやりとりを参考にしました。 澤田聡司さん、小山さん、中野靖治さん、宮本さん、杉村貴士さん、出井秀行さん NARDI ステアリング トヨタ アイシス M10系 16/9~19/4 FET BOSS KIT(FET ボスキット)・NARDI(ナルディ) ステアリングセット ステアリングボス BOSS〔FB539〕/ステアリング〔N807〕、 その他のみなさんに感謝します。 特に、澤田さんから多くの情報と示唆をいただきました。感謝します。

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

メモ:以下のソースではRuntimeExceptionを使用しています。 一般に 15インチカローラ アクシオ140系 全グレードENKEI オール オールワン マシニングレモンイエロー 6.0Jx15ZIEX ZE914F 195/65R15、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)

clazzio シートカバー クラッツィオ プライムタイプ ホンダ エリシオン 型式 RR1/RR2 RR3/RR4 年式 H16/5-H17/9 定員 8人 ≪ 運転席手動/助手席肘掛有/2列目肘掛3本仕様/ヘッドレスト総数8個車用 ≫※2列目回転機構付不可 ※サイドエアバック付車不可のオンラインストアへ!

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

リンク

更新履歴

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

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

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

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

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


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

スカイライン用 ローターセンサーアンチスキツドフロントスカイライン 47970-15U00 日産純正部品豊かな人生のための四つの法則

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