連載
.NETで始めるデザインパターン

第1回 .NET開発におけるデザインパターンの有用性

太陽システム株式会社 中西 庸文
2005/01/12
Page1 Page2

●デザインパターンが適用されて、問題が改善された設計の例

 ここではまず、先ほどのソース・コードにデザインパターンを適用しつつ、リファクタリングした結果の実装コードを示す。

 新しいDeveloperクラスのコードは以下のようになっている。テスト・コードは変更していないので割愛する。

Imports System

Namespace DesignPatterns.Core

  Public Class Developer

    Public Const General As Integer = 0
    Public Const Agile As Integer = 1

    Private _state As IDeveloperState

    Public Sub New(ByVal developerType As Integer)
      If (developerType = General) Then
        Me._state = New GeneralDeveloperState
      Else
        Me._state = New AgileDeveloperState
      End If
    End Sub

    Public Function HowMuchGreenbarLover() As Integer
      Return _state.HowMuchGreenbarLover()
    End Function

    Public Function HowHeavyRefactor() As Integer
      Return _state.HowHeavyRefactor()
    End Function

    Public Function HowHappy() As Integer
      Return _state.HowHappy()
    End Function

  End Class

End Namespace
デザインパターンを適用してリファクタリングしたソース・コード(VB.NET)

 以前のDeveloperクラスのコードと比較してみると、条件判定を行うif文がコンストラクタ内の1カ所のみになっていることに気付くはずだ。

 さらに次のような点にも注意してほしい。

  1. int型のフィールドdeveloperTypeが、新しく定義されたIDeveloperState型のフィールドstateに置き換わっている

  2. コンストラクタでは、指定された開発者の種類によって、新しいクラスのインスタンスが生成されstateに割り当てられている。しかもこの条件判定は、オブジェクト生成に関する条件判定であって、Developerクラスの振る舞いに関する条件判定ではない

  3. 各メソッドの呼び出しがstateオブジェクトに委譲されている

 これらは開発者の種類によるDeveloperクラスの振る舞いの変化が、フィールドの状態変化として実現されていることを示している。このstateのようなオブジェクトは「状態オブジェクト」と呼ばれている。

 新しく追加された状態オブジェクトのインターフェイスとその実装クラスは以下のようになっている。

Imports System

Namespace DesignPatterns.Core

  Public Interface IDeveloperState

    Function HowMuchGreenbarLover() As Integer

    Function HowHeavyRefactor() As Integer

    Function HowHappy() As Integer

  End Interface

  Public Class GeneralDeveloperState : Implements IDeveloperState

    Public Function HowMuchGreenbarLover() As Integer _
      Implements IDeveloperState.HowMuchGreenbarLover
      Return 3
    End Function

    Public Function HowHeavyRefactor() As Integer _
      Implements IDeveloperState.HowHeavyRefactor
      Return 3
    End Function

    Public Function HowHappy() As Integer _
      Implements IDeveloperState.HowHappy
      Return 3
    End Function

  End Class

  Public Class AgileDeveloperState : Implements IDeveloperState

    Public Function HowMuchGreenbarLover() As Integer _
      Implements IDeveloperState.HowMuchGreenbarLover
      Return 5
    End Function

    Public Function HowHeavyRefactor() As Integer _
      Implements IDeveloperState.HowHeavyRefactor
      Return 5
    End Function

    Public Function HowHappy() As Integer _
      Implements IDeveloperState.HowHappy
      Return 5
    End Function

  End Class

End Namespace
状態オブジェクトのインターフェイスとその実装クラス(VB.NET)

 上記コードでは、「一般的な開発者」「アジャイルな開発者」のそれぞれに対する振る舞いを表現する状態オブジェクト用のクラスが存在し、Developerクラスの振る舞いに対してのポリモーフィズムが実現されている。これにより、新しい開発者の種類が増える場合には、新しい状態オブジェクト用のクラスを追加してやるだけでよくなる。開発者の種類による状態オブジェクト生成の条件分岐は併せて修正しなければいけないが、この部分はすでにDeveloperクラス内のコンストラクタ内で局所化されている。

 クラスが増えて複雑な設計になっただけではないかと思われるかもしれないので、改善された設計についてクラス図を用いて考察してみよう。

改善された設計についてのクラス図

 このクラス図では、以前のクラス図では読み取ることができなかった開発者の種類に関する情報が表現されている。また開発者の種類による振る舞いがクラスとして表現されており、Developerクラスの振る舞いが変化することを直感的に理解できる。

 しかし、Developerクラスを利用するユーザーはDeveloperクラス内部の状態オブジェクトの存在は知る必要がない。改善前のDeveloperクラスの設計を使用する場合とまったく同じように扱うことができるのだ。テスト・コードを変更する必要がないことが何よりの証拠である。Developerクラスにとって、テスト・コードは最初のユーザーなのだから。

 要するに、扱うクラスが増えたものの、Developerクラスのユーザーの立場からは、設計は複雑にはなっていないと考えられるのである。

●デザインパターン適用による問題解決のメリット

 今回紹介した例は、「GoFのデザインパターン」の1つである「Stateパターン」を適用した設計改善の例である。「GoF」とは書籍『オブジェクト指向における再利用のためのデザインパターン』の筆者4人を意味する「Gang of Four」の略で、この書籍は23個のデザインパターンを集めてカタログ化したものだ。

 『オブジェクト指向における再利用のためのデザインパターン』では、Stateパターンの目的は次のように記述されている。

オブジェクトの内部状態が変化したときに、オブジェクトが振る舞いを変えるようにする。クラス内では、振る舞いの変化を記述せず、状態を表すオブジェクトを導入することでこれを実現する。

 つまり、クラス内で振る舞いの変化を記述してしまうことが問題で、その問題に対する解決策として、状態を表すオブジェクトを導入するというStateパターンが適用できるのである。

 このように、問題解決の方法があらかじめ文書化されたデザインパターンを適用することで、問題に対する解を自らが考えてから実装するのではなく、先人の知恵を借りて解決することが可能となる。もちろんご覧いただいたように、.NETのシステムにも何の違和感もなく適用できる。

 デザインパターンを適用するメリットはこれだけではない。開発者間のコミュニケーションを向上させられるということも、デザインパターンによる大きなメリットの1つである。開発者間でデザインパターンに対する共通の認識があれば、

「Developerクラスの振る舞いを状態オブジェクトとしてDeveloperクラスから分離しよう。分離した状態オブジェクトのインスタンスを切り替えることで、Developerクラスの振る舞いの変化を表現しよう」

などとクラス図を書きながら説明する代わりに、

「DeveloperクラスにはStateパターンを適用しよう」

の一言で的確に意図を表現できるのである。

 デザインパターンの有用性が何となくでもご理解いただけただろうか。今回はここまでだ。次回からは、より詳細にデザインパターンがどのようなものかについて解説していく。End of Article


 INDEX
  .NETで始めるデザインパターン
  第1回 .NET開発におけるデザインパターンの有用性
    1..NETにおけるデザインパターンの必要性
  2.デザインパターン適用による問題解決のメリット
 
インデックス・ページヘ  「.NETで始めるデザインパターン」


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メールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間