連載:熱血VBプログラマ応援団

第12回 はやりのデザイン・パターンをVBで

― コードの定石に名前を付けるとこんなに便利 ―

株式会社ピーデー 川俣 晶
2004/09/01
Page1 Page2

 Factory Methodパターンの基本的なアイデアは簡単です。主に2つのアイデアから構成されているといえます。

 第1のアイデアは、種類の判断を封じ込めることです。オブジェクト(ここではフォーム)を生成する機能そのものを、特定のメソッドの中に封じ込めてしまい、どんな種類のオブジェクトが生成されるかはすべてそのメソッドの問題とするわけです。

 第2のアイデアは、オブジェクト(フォーム)を生成するメソッドを、継承の機能を用いて、後から自由に追加変更可能とすることです。ここでは、めったに更新しないメイン・プログラムと頻繁に更新されるクラス・ライブラリという2つから構成されるプログラムを想定します。メイン・プログラムからオブジェクト(フォーム)を生成するメソッドを呼び出すコードは変更したくありませんが、実際に呼び出されるメソッドはクラス・ライブラリを更新するだけで変更されるようにしたいのです。

 このようなアイデアを実現するために、Factory Methodパターンは以下の4種類のクラスを組み合わせて実現します。上記のサンプル・コードをFactory Methodパターンで書き換えることを前提に、それぞれの役割を見てみましょう。

■Productクラス

 生成したいオブジェクト(フォーム)を抽象的に表現するクラス。メイン・プログラムはこのクラスのことを知っていて使用することができます。

 ここでは、.NET Frameworkのクラス・ライブラリに含まれるFormクラス(System.Windows.Forms.Form)がそれにあたります。

■ConcreteProductクラス

 生成したいオブジェクト(フォーム)を表現するクラス。「Concrete」とは「具体的な」という意味です。このクラスは、Productクラスを継承して実装します。

 ここでは、FormNormal、FormHoliday、FormShogatsuの3つのフォームがこれにあたります。メイン・プログラムは、これらのクラスのことを知らず、直接呼び出すこともできません。しかし、Productクラスを通して、これらのクラスにアクセスすることができます。容易に入れ替えを行うために、メイン・プログラムではなく、クラス・ライブラリ側に置くことが想定されています。

■Creatorクラス

 オブジェクト(フォーム)を生成する抽象的なメソッドを含んでいるクラス。具体的にオブジェクト(フォーム)を生成する方法を知っているわけではありません。メイン・プログラムは、このクラスを知っていて、このクラスのメソッドを呼び出すことができます。これに相当するクラスは、新たに作成しなければなりません。

■ConcreteCreatorクラス

 オブジェクト(フォーム)を生成する具体的なメソッドを含んでいるクラス。Creatorクラスを継承して実装します。メイン・プログラムは、これらのクラスのことを知らず、直接呼び出すこともできません。しかし、Creatorクラスを通して、これらのクラスにアクセスすることができます。これに相当するクラスも、新たに作成しなければなりません。

 以上から分かるとおり、メイン・プログラムはProductクラスとCreatorクラスを知っているが、ConcreteProductクラスとConcreteCreatorクラスは知らないという構造になります。知らないクラスには依存しませんから、メイン・プログラムを変更することなく、ConecreteProductクラスとConecreteCreatorクラスは自由に変更することができます。そして、メイン・プログラムが知らないクラスであっても、そのクラスのオブジェクトを作成するメソッドを呼び出すことができるため、それを利用できるわけです。

 では、以上を実現したサンプル・コードを次に示します。その前に、サンプル・コードで作成している各クラスと、上記の役割との関連を図示しておきましょう。

 Creatorクラスは以下のようになります。これはメイン・プログラム側に含めておきます。

Public MustInherit Class FormCreator
  Public MustOverride Function CreateForm() As Form
End Class
Creatorクラスとなる「FormCreatorクラス」

 MustInheritキーワードは、継承しなければ使用できないクラスであることを示すキーワードです。また、メソッドに付加されたMustOverrideキーワードは、オーバーライドが必須となるメソッドであることを示します。このメソッドには実行する内容が存在しないので、継承したクラスで中身を与えずには使用できない、ということです。

 これらを呼び出すメイン・プログラム側のコードは以下のようになります。

Private Sub ShowForm(ByVal creator As FormCreator)
  Dim form1 As Form = creator.CreateForm
  form1.ShowDialog(Me)
End Sub
FormCreatorクラスを使用するメイン・プログラムのShowFormメソッド

 このコードには、最初のサンプル・コードのShowFormメソッドと同じ機能が与えられています。機能は同じであるのに、行数がぐっと短くなっていることが分かると思います。それは、仕事の大半をCreateFormメソッドに入れてしまったからです。そして、CreateFormメソッドによって実行される内容は、メイン・プログラム側には含まれていません*

* このShowFormメソッドにデザイン・パターンを使用しない元のサンプル・コードにはなかったパラメータcreatorが追加されているのは、ConcreteCreatorクラス(具体的には次のMyFormCreatorクラス)のインスタンスをメイン・プログラムの外から受け取って利用する場合を想定しているためです。

 ConcreteCreatorクラスは以下のようになります。これはクラス・ライブラリ側に含めておきます。

Public Class MyFormCreator
  Inherits FormCreator

  Public Overrides Function CreateForm() As System.Windows.Forms.Form
    Dim today As DateTime = DateTime.Today

    If today.Month = 1 And today.Day = 1 Then
      CreateForm = New FormShogatsu
    ElseIf today.DayOfWeek = DayOfWeek.Sunday Then
      CreateForm = New FormHoliday
    Else
      CreateForm = New FormNormal
    End If
  End Function
End Class
ConcreteCreatorクラスとなる「MyFormCreatorクラス」

 これが、実際にオブジェクト(フォーム)を生成する部分です。Overridesキーワードは、継承元のクラスの同名メソッドを置き換えることを示しています。つまり、継承元クラスのCreateFormメソッドを呼び出すと、実際にはこのCreateFormメソッドが呼び出されることになるわけです。

 さて、これらのコードを見て分かるとおり、フォームの種類と、それを呼び出す条件のすべてはクラス・ライブラリ側に含まれます。そして、それらのコードを含むクラスと、個々のフォームを実現するクラスを参照するコードは、メイン・プログラム側には含まれないことになります。

 これによって、このシステムの中で、変更が予想される部分と、変更したくない部分を分離することができたわけです。特定の日付にのみ表示されるフォームを追加する場合には、そのフォームをデザインしてクラスを用意し、そのフォームを生成するコードをMyFormCreatorクラスのCreateFormメソッドに書き足して、クラス・ライブラリのみを再ビルドするだけで済みます。

 もちろん、デザイン・パターンを使わなくても、同じことを実現することは容易です。しかし、すでに完成されているパターンを活用したことで、あれこれ思い悩んだり試行錯誤したりする必要がなく、無駄な時間を使わずに済んでいます。そして、何より、「よし、Factory Methodパターンを使おう!」と宣言するだけでほかの技術者と意思疎通できる点が大きな収穫といえます。

デザイン・パターン活用への道を開いたVisual Basic .NET

 さて、このFactory Methodパターンはデザイン・パターンの1つに過ぎません。デザイン・パターンには、ほかにもさまざまなパターンが含まれています。それらは実績のあるパターンをカタログ化したという経緯から分かるとおり、現実に役に立つものです。それにもかかわらず、これまでVBの世界であまり使われてこなかったのはなぜでしょうか。

 その問いは、上記のサンプル・コードをVisual Basic 6.0(以下、VB 6)上で動くように書き換えてみると分かると思います。このサンプル・コードは継承を使用しているため、そのままではVB 6では動作しません。このサンプル・コードの場合に限れば、インターフェイスの機能などを使うことで、ある程度同じような機能は実現できるかもしれませんが、すべてのケースで同じことができるわけではありません。つまり、デザイン・パターンは、オブジェクト指向プログラミングのためのカタログであり、それゆえに多くのパターンが継承の機能を必要とします。それが、VB 6までのVisual Basicでデザイン・パターンを適用しにくい理由だったのではないかと思います。

 しかし、いまやVisual Basic. NETは継承をサポートし、そのような理由は過去のものになりました。Visual Basic .NETが、VBプログラマにデザイン・パターンを活用する道を開いてくれたといえます。

 もちろん、デザイン・パターンはあらゆる問題を解決してくれる万能薬というわけではなく、使いすぎるとかえってプログラムを分かりにくくする劇薬としての側面も持っています。しかし、パターンのカタログ化という考え方は強力であり、デザイン・パターンはチャレンジする意義のある技術だと思います。VBプログラマがそれに取り組む道が開かれたいま、ためらう理由はないでしょう。

 頑張れVBプログラマ、君たちが使うVisual Basic .NETは取り組む価値のある可能性に満ちたプログラム言語だ!End of Article

 

 INDEX
  [連載]熱血VBプログラマ応援団
  第12回 はやりのデザイン・パターンをVBで
    1.デザイン・パターンって何?
  2.デザイン・パターンを実際に使ってみよう
 
インデックス・ページヘ  「熱血VBプログラマ応援団」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH