デザインパターン-ChainOfResponsibility

Chain Of Responsibilityパターンとは

Chain Of Responsibilityパターンは、複数のオブジェクトを鎖状につなぎ、その中の任意のオブジェクトが要求を処理するまで、順次その鎖に沿って要求を受流していくパターンです。

オブジェクトが自分では処理しきれないタスクであると判断したら、処理の責任を次のオブジェクトに処理を渡すという連鎖構造における「要求のたらい回し」といえます。

「Chain of Responsibility」とは「責任の連鎖」という意味です。


Chain Of Responsibilityパターンの利点

  • 要求側は処理を呼び出す最初の相手だけ知っていれば良い
    • 利用者側は「この要求はこのオブジェクトが処理する」などということを利用者側が意識する必要がなくなります。
  • 処理の連鎖の修正が容易
    • 処理の優先度は連鎖構造を変更するだけで完了します。
  • 各自の処理に専念できる
    • 処理側は要求に対して自身で処理できる場合は処理し、できない場合はその要求を次のオブジェクトに渡すだけという役割分担が明確となります。

Chain Of Responsibilityパターンの欠点

  • 処理が遅いこと
    • 連鎖を辿っていくことは、線形探索を行うことと類似します。
    • 目的の処理を行うまでに、無駄な処理を発生してしまいます。

構成要素

  • Handler(抽象取扱者・処理者)
    • 要求を処理するインタフェースを定義します。
    • 自身で処理できない要求の場合に受流す先を格納するフィールドを定義します。
  • ConcreteHandler(具象取扱者・具体的な処理者)
    • 「Handler」のインタフェースを実装します。
    • 実際に要求を処理する。
  • Client(利用者)

rubyによるChainOfResponsibilityパターンの実装

FizzBuzz問題をChainデザインパターンで記述します。

3の倍数のときは数の代わりにFizzと、5の倍数のときはBuzzとプリントし、3と5両方の倍数の場合にはFizzBuzzとプリントすること。

無駄な実装であり、処理速度は遅いですが、オブジェクト間の拡張性があります。


#!/usr/bin/env ruby

# Handler(抽象取扱者・処理者)
class Handler
  def initialize()
    @next = nil
  end
  # チェーンの作成
  def set_next(next_obj)
    @next = next_obj
  end

  # 要求の受付
  def request(number)
    if(check_number(number))
      return(true)
    elsif(@next != nil)
      @next.request(number)
    else
      puts(number)
    end
  end
  def check_number
  end
end

# ConcreteHandler(具象取扱者・具体的な処理者) 
class FizzBuzz < Handler
  def check_number(number)
    return(false) if not((number % 3 == 0) and (number % 5 == 0))
    puts("Fizz Buzz(#{number})")
    return(true)
  end
end

class Fizz < Handler
  def check_number(number)
    return(false) if not(number % 3 == 0)
    puts("Fizz(#{number})")
    return(true)
  end
end

class Buzz < Handler
  def check_number(number)
    return(false) if not(number % 5 == 0)
    puts("Buzz(#{number})")
    return(true)
  end
end

# 連鎖の作成
fbzz = FizzBuzz.new
buzz = Buzz.new
fizz = Fizz.new
fbzz.set_next(buzz)
buzz.set_next(fizz)

for e in 1..100
  fbzz.request(e)
end


関連ページ