デザインパターン - ylb.jpylb.jp/iphonekyotod/pdf/04designpatterns.pdf ·...
TRANSCRIPT
Copyright 2009 T. Ogihara
Cocoa / Cocoa touchのデザインパターン
2009. 08 荻原剛志
Copyright 2009 T. Ogihara
デザインパターンとは特にオブジェクト指向における、ソフトウェア部品の組み合わせ方のパターン
過去のソフトウェア設計者が見出し、実践を積んできた設計ノウハウ
これらをまとめ、名前をつけ、再利用しやすいようにカタログ化したもの
Mac OS X / Cocoa touch には、デザインパターンで説明できるAPIの構成がいくつかある
Copyright 2009 T. Ogihara
デザインパターンを学ぶと洗練された設計パターンの典型を知ることができる
個々の設計者の「車輪の再発明」を防ぐ
その手法の利点、欠点が事前に明らか
概念が名付けられており、意志疎通に有用
E. Gamma, R. Helm, R. Johnson, and J. Vlissides, “Design Patterns Elements of Reusable Object-Oriented Software”, 1995(オブジェクト指向における再利用のためのデザインパターン 改訂版, SoftBank Publishing)F. Buschmann, R. Meunier, H. Rohnert, P. Sommerlad, and M. Stal, “Pattern-Oriented Software Architechture: A System of Petterns”, 1996(ソフトウェアアーキテクチャ ソフトウェア開発のためのパターン体系, 近代科学社)
参考図書
[POSA]
[GoF]
Copyright 2009 T. Ogihara
ソフトウェアアーキテクチャソフトウェアは多くの構成要素(コンポーネント)から構成されている。コンポーネントの組み合わせによるソフトウェアの骨組みを表す。✦ 骨組みの一部にデザインパターンが含まれたり、複数のデザインパターンの組み合わせが全体の骨組みを構成することはあり得る。
コンポーネント、コンポーネント相互間と環境との関係、およびその設計と進化を導く原理のうちに具現化された、システムの基本構造である‣ Architecture: the fundamental organization of a system embodied in its
components, their relationships to each other and to the environment and the principles guiding its design and evolution. (IEEE 1472: ANSI/IEEE 1471-2000)
Copyright 2009 T. Ogihara
図式表現(1)
クラス
UMLと順番が逆
インスタンス化
Class Name
操作()操作()データデータ
インスタンス化する側
インスタンス化される側
操作やデータは省略されることがある
疑似コードが添付されることがある
(UMLはこの矢印で「依存」を表現)
実装 擬似コード
Copyright 2009 T. Ogihara
図式表現(2)
継承 スーパークラス
サブクラス
スーパークラス
サブクラス1 サブクラス2
抽象クラス、抽象オペレーションはイタリックで表現
AbstractOperation()Abstract Class
Operation()Concrete Class
Copyright 2009 T. Ogihara
図式表現(3)
オブジェクト間の関係
A B
A B
AはBを「知っている」。AからBの操作を利用できる。
AはBを「一部として保有する」。BはAの構成要素である。AとBのライフタイムは同じ。AからBの操作を利用できる。
B 複数個のBと関係があることを示す。
知り合い(acquaintance)
集約(aggregation)
Copyright 2009 T. Ogihara
Model-View-Controller (1)GUIを持つアプリケーションで、必須と言ってよいデザインパターンModelはシステムの核となるデータと機能を持つ。特定のプラットフォームや入出力から独立している。Viewはユーザに対して情報を提示する。Controllerはイベントを処理し、Viewの表示とModelのデータを書き換える。
controller
model
view
Model-View-Controller (2)
Controller
Observerupdate()
Viewactivate()display()update()
抽象クラス
• ViewとControllerは対で存在• ひとつのModelにViewが複数あってもよい• あるControllerがModelを変更すると、それが他のViewの表示すべてに反映される
Modelattach(observer)detach(observer)notify()getData()service()core datasetOfObservers
handle(event)update()
observers
controllermodel
model
view
[POSA]
Copyright 2009 T. Ogihara
デリゲートあるオブジェクトが、処理できないメッセージを受け取った時に別のオブジェクトに処理を代行してもらう機構。(委譲、デリゲーションとも呼ぶ)
Cocoa環境の場合には、付加的な処理を行ってくれる「増設」オブジェクトといった感じが近い
Copyright 2009 T. Ogihara
デリゲートの例
デリゲート
NSApplication 自作の任意のクラス
デリゲートが指定されており、あらかじめ決められたメソッドが実装されていれば、必要に応じてメッセージが送られる。
・アプリケーションの初期化が終わった → 追加の初期化処理・アプリケーションが隠される → アニメーションなどの停止・アプリケーションが終了する → 終了してもよいか? ...
NSWindow(ウィンドウ)など、デリゲートを用いたプログラミングを前提に設計されているクラスは多い。
(アプリケーション管理)
Copyright 2009 T. Ogihara
デリゲートとサブクラスの違いデリゲートは実行中に動的に変更もできる。複数のオブジェクトに対してひとつのオブジェクトがデリゲートになることもできる。基本的な動作と、追加・拡張する機能を明確に分離してプログラムを作成できる。頻繁に使われる汎用の部品などに有効。デリゲートを持つクラスを簡単に実現するための、言語上の仕組みはない。
- (void)setDelegate:(id)obj;- (id)delegate;
アクセサは以下を使うのが普通
Copyright 2009 T. Ogihara
Template Method パターン
アルゴリズムの記述において、サブクラスで決定すべき処理は抽象メソッドとしておき、実装の変更を容易にする。
ApplicationAddDocument()OpenDocument()DoCreateDocument()CanOpenDocument()AboutToOpenDocument()
DocumentSave()Open()Close()DoRead()
MyDocument MyApplication
docsif ( ! CanOpenDocument(name)) { // cannot handle this document return;}
Document* doc = DoCreateDocument();
if (doc) { _docs->AddDocument(doc); AboutToOpenDocument(doc); doc->Open(); doc->DoRead();}
DoRead() DoCreateDocument()CanOpenDocument()AboutToOpenDocument()
(GoF: 振る舞いに関するパターン)
Copyright 2009 T. Ogihara
Template Method パターン
✦ アルゴリズムの不変な部分をまず実装し、振る舞いが変わり得る部分の実装はサブクラスに残しておく場合。
✦ サブクラス間で共通の振る舞いをする部分は抜き出して、これを共通のクラスに局所化する場合。•同じコードがあちこちに現れることがないようにする
✦ サブクラスの拡張を制御する場合。•特定の時点で “hook” operation を呼び出すテンプレートメソッドを定義することができる。
オブジェクト指向プログラミングで一般的に使われる手法である。Cocoa / Cocoa touch でも、サブクラス化を前提とした多くのクラスで使われている。
Copyright 2009 T. Ogihara
Observer パターンオブジェクトの状態変化を他のオブジェクトに自動的に知らせる。
a b cx 60 30 10y 50 30 20z 80 10 10
01020304050
a b c
20%
30%50%
a = 50b = 30c = 20subject
変更の通知変更の通知変更の
通知
値の取得、変更
値の取得、変更
値の取得、変更 各オブジェクトが
互いの実装を知る必要はない。
(GoF: 振る舞いに関するパターン)
Copyright 2009 T. Ogihara
Observer パターン
構造
Update()Observer
Attach(Observer)Detach(Observer)Notify()
Subject
return subjectState;
for all o in observers { o->Update();}
Update()ConcreteObserver
observerState
observers
GetState()SetState()
ConcreteSubject
subjectState
subject
observerState = subject->GetState();
変化があったら observerに知らせる
通知があったら subjectの状態を調べる
Copyright 2009 T. Ogihara
Observer パターン抽象化により、2つの面が、一方が他方に依存しているという形で現れる場合。これらの面をそれぞれ別々のオブジェクトにカプセル化することにより、それらを独立に変更したり、再利用することが可能になる。あるオブジェクトを変化させるとき、それに伴い他のオブジェクトも変化させる必要があり、しかも変化の必要があるオブジェクトを動的に決定したい場合。オブジェクトが、他のオブジェクトに対して、そのオブジェクトが何かを仮定せずに通知できるようにする場合。Foundation では NSNotificationCenterクラスを用いて実現する(通知)。AppKit で Cocoaバインディングを使っても実現できる。
Copyright 2009 T. Ogihara
Singleton パターンあるクラスのインスタンスがただひとつであることを保証する。
インスタンスインスタンス化の操作を用意し、常に同じインスタンスを値として返す。
SingletonClassstatic Instance()
static uniqueInstance
return uniqueInstance;
(GoF: 生成に関するパターン)
構造 クライアントは、唯一のインスタンスに対し、必ずクラスオペレーション Instance を通してアクセスする。
Copyright 2009 T. Ogihara
Singleton パターン適用可能性:クラスに対してインスタンスが1つしか存在してはならず、また、公開されたアクセスポイントを通してそのインスタンスにアクセスできなければならない場合。
Cocoa / Cocoa touch では多くのクラスに「常にデフォルトのインスタンスを返す」クラスメソッドが用意されている。
[UIApplication sharedApplication]
[UIPasteboard generalPasteboard]
[UIAccelerometer sharedAccelerometer]
例
Copyright 2009 T. Ogihara
Chain of Responsibility パターン
鎖状につながれた複数のオブジェクトにイベントを渡し、いずれかのオブジェクトにそれを処理する機会を与える。
アプリケーション
セーブパネル プリントパネル
印刷ボタンキャンセルボタン
イベントが渡される向き
ボタンが処理するイベントならボタンのオブジェクトが処理。そうでなければパネルが処理。パネルも処理できなければアプリケーションが処理する。
(GoF: 振る舞いに関するパターン)
テキスト
Copyright 2009 T. Ogihara
Chain of Responsibility パターン
HandleRequest()Handler
構造Client
successor
クライアントが要求を出すと、ある ConcreteHandler オブジェクトがそれに対する処理を引き受けるまでは、その要求はチェーンに沿って転送されていく。
HandleRequest()ConcreteHandler2
HandleRequest()ConcreteHandler1
AppKit / UIKit で Viewの階層構造に対するイベント処理に用いられ、レスポンダ・チェーンと呼ばれる。エラーをメソッドの呼び出し側に返す際にも使われ、エラー・レスポンダ・チェーンと呼ばれる。
Copyright 2009 T. Ogihara
Factory Method パターン
インスタンス生成のインタフェースだけを提供し、実際のインスタンスの生成方法はサブクラスが定義する。
ファイル新規...ファイルを開く...保存別名で保存...
CreateDocument()OpenDocument()SaveDocument()
ApplicationCreate()Open()Save()
Documentdocs
具体的なアプリケーション 具体的な
文書メッセージ送信
(GoF: 生成に関するパターン)
Copyright 2009 T. Ogihara
Factory Method パターン
MyApplicationCreateDocument()
構造
MyDocument
Document *doc;doc = CreateDocument();docs.Add(doc);doc->Open();
CreateDocument()NewDocument() OpenDocument()
ApplicationCreate()Open()Close()Save()
Documentdocs
return new MyDocument;
AppKitには NSDocument、 NSDocumentController、および NSWindowController クラスが用意されている。操作対象のファイルに応じ、それぞれのサブクラスを定義する。
Copyright 2009 T. Ogihara
Bridge パターン
抽出されたクラスとその実装を、橋渡しをする構造で分離し、実装を隠蔽する。
Bridge
DrawText()DrawRect()
Windowimp DevDrawText()
DevDrawRect()
WindowImp
TransientWindowIconWindowDevDrawText()DevDrawRect()
DevDrawText()DevDrawRect()
XWindowImp PMWindowImp
XDrawLine();
実装する環境に応じて、 Windowクラスの imp を切り替えればよい。
XDrawString();
(GoF: 構造に関するパターン)
Copyright 2009 T. Ogihara
Bridge パターン 構造
Operation()Abstraction
imp
OperationImp()Implementor
RefinedAbstraction
imp->OperationImp();
OperationImp()ConcreteImplementorA ConcreteImplementorB
OperationImp()
Abstraction クラスは、クライアントからの要求を Implementor のオブジェクトへ転送する。
Client
Copyright 2009 T. Ogihara
Bridge パターン抽出されたクラスとその実装の永続的な結合を避けたい場合。抽出されたクラスとその実装の両方を、サブクラスの追加により拡張可能にすべき場合。
AppKitで画像を扱う NSImage は、イメージの実体の表現を NSImageRep クラスに任せている。 NSImageRepは具体的なデータ形式に対応して NSBitmapImageRep、 NSPDFImageRep などのサブクラスを持つ。 NSImageRepのサブクラスは追加することもできる。
Copyright 2009 T. Ogihara
Proxy パターンあるオブジェクトへのアクセスを制御するために、代理となるオブジェクトを提供する。(別名 Surrogate、Wrapper)
2007年6月に米国、欧州で発売され、ブームを巻き起こしたアッパレ社製の携帯端末「iPbone」が7月11日に国内販売を開始の予定。大手メディア各社の事前アンケートでは、半数近くが「興味がある」、「検討する」と回答。音楽や映像を楽しめる点が魅力に挙げられていますが、おサイフ携帯機能やワンセグが使えないことに不満もあるようです。
2007年1月に全世界で発売され、ブーイングを巻き起こしたマグロソフト社のパソコン用基本ソフト「Windowz Bista」。ニュース各社が行ったアンケート調査では、半数以上が「購入予定がない」、「XPを使う」、「様子を見る」と回答。何が新しいのか利用者に分かりにくい上に、処理能力の高い新型マシンに買い替えなければ快適に動作しない点も不満を増大させている点とか。
ITトレンドニュース
?
Draw()Load()
Graphic
Draw()Load()
ImageProxyDraw()Load()
Imageimage
ImageProxy
文字などと同様なグラフィック要素として扱うと同時に、画像がロードできるまでは代わりに枠を表示しておく。
(GoF: 構造に関するパターン)
Copyright 2009 T. Ogihara
Proxy パターン適用可能性:以下の4つの類型に分類できる✦ remote proxy は、別のアドレス空間にあるオブジェクトのローカルな代理を提供する。
✦ virtual proxy は、コストの高いオブジェクトを要求があり次第生成する。
✦ protection proxy は、実オブジェクトへのアクセスを制御する。オブジェクトごとに異なるアクセス権が必要なときには、この protection proxy は有用である。
✦ smart reference は、通常のポインタに代わるものである。オブジェクトがアクセスされるときに、その smart reference はさらにアクションを実行する。
Foundation には NSProxy があり、分散オブジェクトへのメッセージの転送に使われている。