250 likes | 359 Views
オブジェクト指向言語 ~ Prototype 編~. 法政大学大学院情報科学研究科 黄研究室 田村 寿浩. 0.目次. 基本的な考え方 サンプルケース 実装方法 UML図 まとめ 関連するパターン 浅いコピーと深いコピー 参考文献. 1.基本的な考え方. Prototype の意味は“試作品”、“ひな型” 予め用意してある“ひな型”からインスタンスを生成する! デザインパターンのカテゴリーでは、“オブジェクトの生成”. 2.サンプルケース. クライアントから、以下の種類のオブジェクトが欲しいとの要求があった 普通のどら焼き 栗入りのどら焼き
E N D
オブジェクト指向言語~Prototype編~ 法政大学大学院情報科学研究科 黄研究室 田村 寿浩
0.目次 • 基本的な考え方 • サンプルケース • 実装方法 • UML図 • まとめ • 関連するパターン • 浅いコピーと深いコピー • 参考文献
1.基本的な考え方 • Prototypeの意味は“試作品”、“ひな型” • 予め用意してある“ひな型”からインスタンスを生成する! • デザインパターンのカテゴリーでは、“オブジェクトの生成”
2.サンプルケース • クライアントから、以下の種類のオブジェクトが欲しいとの要求があった • 普通のどら焼き • 栗入りのどら焼き • 白餡のどら焼き • ジャンボどら焼き
2.サンプルケース • 実装例 standard big main white Mallon それぞれのオブジェクトについてクラスを作って呼び出す
2.サンプルケース • その後クライアントから、以下の種類のオブジェクトを追加して欲しいとの要求があった • 栗入りのジャンボどら焼き • 白餡のジャンボどら焼き • ミニどら焼き
2.サンプルケース 前の実装例のようにオブジェクト毎にクラスを作っていては、クラスだらけになってしまう • クラスを出来るだけ少なくする方法は無いか? • それぞれのオブジェクトは材料の種類・分量が異なるだけで、だいたいの構造は同じ • Prototypeパターン
2.サンプルケース • 元になるどら焼きクラスを作って、コンストラクタの変数の値によって、異なる種類のどら焼きを作る Dorayakiクラス Class Dorayaki{ int size; //どら焼きの大きさ booleankuri; //栗入りかどうか boolean color; //餡子の色 Dorayaki(intsize,booleankuri,boolean color){ this.size = size; this.kuri = kuri; this.color = color; } /*略*/ }
2.サンプルケース • 既に作ってあるオブジェクトと同じオブジェクトが欲しくなった場合、新しくオブジェクトを作るのではなく、既存の物を複製する Mainクラス Dorayaki d1 = new Dorayaki(2, true, true); Dorayaki d2 = new Dorayaki(2, true, true); ↓ Dorayaki d1 = new Dorayaki(2, true, true); Dorayaki d2 = d1.createDorayaki();
2.サンプルケース • 既に作ってあるオブジェクトと同じオブジェクトが欲しくなった場合、新しくオブジェクトを作るのではなく、既存の物を複製する public class Dorayakiimplements Cloneable{ /*略*/ DorayakicreateDorayaki() { Dorayaki d = null; try { d = (Dorayaki) this.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return d; } } CloneableをimplementsしないとCloneNotSupportedExceptionが 発生します
2.サンプルケース • 実行結果 public class Main { public static void main(String[] args) { Dorayaki d1 = new Dorayaki(2, true, true); Dorayaki d2 = d1.createDorayaki(); System.out.println("d1 :" + d1); System.out.println("d2 :" + d2); } }
2.サンプルケース • クライアントから、以下のオブジェクトも追加してほしいという要望があった • 普通の大判焼き • 白餡の大判焼き • カスタードクリームの大判焼き
2.サンプルケース • どら焼きと大判焼きは構造が異なるので、新たにクラスを作る必要がある • しかし、複製を作る部分は共通なのでinterfaceを作る public interface Prototype extends Cloneable{ public Prototype create(); //オブジェクトの複製を作るメソッド public String toString(); //オブジェクトを表示するメソッド }
2.サンプルケース //どら焼きクラス public class Dorayaki implements Prototype { /*略*/ public Prototype create() {//複製を作るメソッド Dorayaki d = null; try { d = (Dorayaki) this.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return d; } public String toString() {//表示 return "大きさ: "+ size + " 栗: "+ kuri + " 餡の色: "+ color; }} //大判焼きクラス public class Ohbanyaki implements Prototype { String type; // 大判焼きの中身 Ohbanyaki(String type) {//コンストラクタ this.type = type; } public Prototype create() {//複製を作るメソッド Ohbanyaki o = null; try { o = (Ohbanyaki) this.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return o; } public String toString() {//表示 return "中身: "+ type; }}
2.サンプルケース • 実行結果 public class Main { public static void main(String[] args) { Dorayaki d1 = new Dorayaki("普通", true, true); Dorayaki d2 = (Dorayaki) d1.create(); Ohbanyaki o1 = new Ohbanyaki("クリーム"); Ohbanyaki o2 = (Ohbanyaki) o1.create(); System.out.println("d1 :" + d1); System.out.println("d2 :" + d2); System.out.println("o1 :" + o1); System.out.println("o2 :" + o2); } }
4.UML図 Client ClientオブジェクトはConcretePrototypeオブジェクトにコピーを依頼する
3.実装方法 • Cloneableをextendsしたinterfaceを作成する • Interfaceにコピ-を行うメソッドを宣言する • コピーしたいオブジェクトクラス内でコピーを行うメソッドを実装する • (コピーで生成されたオブジェクトを初期化する)
5.まとめ • オブジェクトの種類が多すぎて、クラスにまとめるのが困難な時にPrototypeパターンを利用することにより、それを避けることが出来る • クラスのインスタンスの生成が難しい場合、Prototypeパターンでインスタンスをコピーした方が楽 • クライアントは、複製するクラスの詳細を知らなくてもよい 問題点としては、各サブクラスがコピーを行うメソッドを実装しなければならない
6.関連するパターン • Mementoパターン Mementoパターンでは、スナップショットとアンドゥを行うために現在 のインスタンスの状態を保持する Prototypeパターンでは現在のインスタンスと同じ状態の別のインス タンスを作る • Compositeパターン • Decoratorパターン これらのパターンを多用すると、複雑な構造のインスタンスが動的 に作られることがある。この時、Prototypeパターンを使うと便利なこ とがある
7.浅いコピーと深いコピー • Javaでは、clone()というオブジェクトのコピーを行うメソッドがある • コピーされるオブジェクトがintやdoubleなどの組み込み型変数は値として格納されているので完全なコピーが可能 • 一方オブジェクト型変数は参照がコピーされるので、コピーしたオブジェクトとコピーされるオブジェクトで、同じオブジェクトを参照することになる • これを浅いコピー(shallow copy)という
7.浅いコピーと深いコピー 車A 浅いコピーの例 タイヤ1 タイヤ2 タイヤ3 タイヤ4 車B 車Aのタイヤ1がパンクすると、車Bのタイヤ1もパンクする
7.浅いコピーと深いコピー • 深いコピー(deep copy)にするには →コピーを行うオブジェクトだけでなく、そのオブジェクトから参照されているオブジェクトのコピーも同時に行う
7.浅いコピーと深いコピー 車A 深いコピーの例 タイヤ1 タイヤ2 タイヤ3 タイヤ4 車B タイヤ1 タイヤ2 タイヤ3 タイヤ4 車Aのタイヤ1がパンクしても、車Bのタイヤ1はパンクしない
8.参考文献 • Java言語で学ぶデザインパターン入門(結城 浩著) • オブジェクトの複写 http://www.asahi-net.or.jp/~DP8T-ASM/java/tips/ObjectCopy.html • オブジェクト指向における再利用のためのデザインパターン (GOF本の日本語訳本) • 実践!!デザインパターン(近藤 博次著)
9.備考 • Cloneメソッドで生成されたオブジェクトは空のコンストラクタを呼びません。