前回はObjective-CにおけるDecoratorパターンの実装を解説した。今回は、例によってCocoaでのDecoratorの実例を紹介しよう。

Decoratorパターンの発想は、GUIフレームワークのスクロールビューやボーダービューから得られたものだろう。ここでの実例探しも、もちろんこれらから入る。Cocoaでの、この種のdecorationを目的としたビューを紹介しよう。NSBoxとNSScrollViewだ。

ボーダーを提供するNSBox

まずはボーダー、つまり境界線を描くためのクラスだ。既存のビューの周りに境界線を描く事を目的とする。Cocoaでは、NSBoxというクラスがこの種のクラスにあたる。

現在のところ、NSBoxでは2種類のボーダーが提供されている。1つは内部が窪んだように見せるもの。もう1つは、よくあるラインスタイルのものだ。

NSBoxでは、内部にビューを配置することができる。この内部に入れることのできるビューも、NSBox自身も、NSViewというクラスを継承している。どちらも同じクラスから継承しているというDecoratorパターンの特徴を備えている。もちろん、NSBoxの中にNSBoxを入れることもできる。

NSBoxの用語では、中に入れるビューのことをコンテントビューと呼ぶ。コンテントビューにアクセスするために、以下のメソッドが用意されている。

List 1.

// コンテントビューを取得する
- (id)contentView
// コンテントビューとのマージンを取得する
- (NSSize)contentViewMargins
// コンテントビューを設定る
- (void)setContentView:(NSView*)view
// コンテントビューとのマージンを設定する
- (void)setContentViewMargins:(NSSize)offsetSize

コンテントビューを取得/設定するためには、contentView、setContentView:というメソッドを使う。また、NSBoxとコンテントビューの間のマージンを設定することもできる。それには、setContentViewMargins:というメソッドを使うわけだ。

NSBoxでのDecoratorパターンを図に表してみよう。もともとDecoratorパターンはシンプルなものなので簡単な図になるが、次のようになる。

NSBoxがDecorator、その継承元となるNSViewがComponentということになる。

ところで、この連載の第73回「Composite (2)」で、NSViewはCompositeパターンとして登場した。そのときに、NSViewは階層構造を構成しており、サブビューとして子となるビューを管理していると説明した。このサブビューと、コンテントビューの関係はどうなっているのか?

実は、コンテントビューは、サブビューの中の1つ、という位置づけになる。ただし、マージンを設定できるなど、特殊なサブビューとなる。

スクロール機能を提供するNSScrollView

続いて紹介するのは、スクロール機能を提供するNSScrollViewだ。これこそ、Decoratorの代表的パターンだろう。

NSScrollViewも先ほどと同様に、NSViewを継承している。Decoratorパターンを踏襲しているわけだ。

スクロールビューの機能は、ボーダーよりも少し複雑である。なぜなら、スクロール領域のクリッピングを行わないといけないからだ。そこで、NSScrollViewでは、ドキュメントビューとコンテントビューという構造を使用している。ドキュメントビューは、スクロールビューに表示するビュー全体。コンテントビューは、それをクリッピングするためのビューだ。

これらに加えて、スクロールバーも別のビューとして実装されている。したがって、NSScrollViewのビュー階層を図で表すと、次のようになるだろう。

この図では、下がルートビューであり、上に向かうとそのサブビューになる。まず、ルートとしてあるのは、NSScrollView。NSScrollViewは、スクロールバーとなるNSScrollerとコンテントビューをサブビューとして持つ。コンテントビューは、NSClipViewというクリッピング機能を持つビューになる。このコンテントビューのサブビューとして、ドキュメントビューがある。ドキュメントビューが、スクロールの対象となるビューだ。

Decoratorパターンの用語を使えば、DecoratorとなるのがNSScrollView。Componentとなるのはドキュメントビューということになる。

NSScrollViewから、コンテントビュー、ドキュメントビューにアクセスするためのメソッドも紹介しておこう。

List 2.

// コンテントビューを取得する
- (NSClipView*)contentView
// コンテントビューを設定する
- (void)setContentView:(NSClipView*)view
// ドキュメントビューを取得する
- (id)documentView
// ドキュメントビューを設定する
- (void)setDocumentView:(NSView*)view

このように、コンテントビュー、ドキュメントビューのために、特別なメソッドが用意されている。それと同時に、これらのビューは、サブビューとしてもアクセスできるところに注意してほしい。つまり、通常のビュー階層構造を利用しながら、そこに特殊なビューを定義しているのだ。

これは、Decoratorパターンが、Compositeパターンを利用して成り立っているということを説明するものになるだろう。

提供:毎日キャリアバン ク

毎日キャリアバンクではITエンジニア出身のキャリアコンサルタントで形成する IT専門のチームを編成し、キャリアに応じた専任コンサルタントがご相談を承り ます。キャリアチェンジから市場価値の可能性、ご収入などの相談から面接のア ドバイスまでお気軽にご相談ください。求人情報誌や転職情報サイトなどで一般 に公開されていないような「急募求人案件」も随時ご紹介が可能です。まずはご 登録ください!