![Mediator](/images/patterns/cards/mediator-mini.png?id=a7e43ee8e17e4474737b1fcb3201d7ba)
Mediator を Ruby で
Mediator は、 振る舞いに関するデザインパターンの一つで、 プログラムのコンポーネント間の通信を特別なメディエーター・オブジェクトを通して行うことで、 結合を疎にします。
Mediator により、 個々のコンポーネントは、 何十ものクラスへの依存がなくなるため、 変更、 拡張、 再利用が容易になります。
複雑度:
人気度:
使用例: Ruby コードで Mediator パターンがよく使われるのは、 アプリの GUI コンポーネント間の通信のやりとりです。 Mediator は、 MVC パターンの C の部分、 Controller と同義語です。
概念的な例
この例は、 Mediator デザインパターンの構造を説明するためのものです。 以下の質問に答えることを目的としています:
- どういうクラスからできているか?
- それぞれのクラスの役割は?
- パターンの要素同士はどう関係しているのか?
main.rb: 概念的な例
# The Mediator interface declares a method used by components to notify the
# mediator about various events. The Mediator may react to these events and pass
# the execution to other components.
class Mediator
# @abstract
#
# @param [Object] sender
# @param [String] event
def notify(_sender, _event)
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
end
class ConcreteMediator < Mediator
# @param [Component1] component1
# @param [Component2] component2
def initialize(component1, component2)
@component1 = component1
@component1.mediator = self
@component2 = component2
@component2.mediator = self
end
# @param [Object] sender
# @param [String] event
def notify(_sender, event)
if event == 'A'
puts 'Mediator reacts on A and triggers following operations:'
@component2.do_c
elsif event == 'D'
puts 'Mediator reacts on D and triggers following operations:'
@component1.do_b
@component2.do_c
end
end
end
# The Base Component provides the basic functionality of storing a mediator's
# instance inside component objects.
class BaseComponent
# @return [Mediator]
attr_accessor :mediator
# @param [Mediator] mediator
def initialize(mediator = nil)
@mediator = mediator
end
end
# Concrete Components implement various functionality. They don't depend on
# other components. They also don't depend on any concrete mediator classes.
class Component1 < BaseComponent
def do_a
puts 'Component 1 does A.'
@mediator.notify(self, 'A')
end
def do_b
puts 'Component 1 does B.'
@mediator.notify(self, 'B')
end
end
class Component2 < BaseComponent
def do_c
puts 'Component 2 does C.'
@mediator.notify(self, 'C')
end
def do_d
puts 'Component 2 does D.'
@mediator.notify(self, 'D')
end
end
# The client code.
c1 = Component1.new
c2 = Component2.new
ConcreteMediator.new(c1, c2)
puts 'Client triggers operation A.'
c1.do_a
puts "\n"
puts 'Client triggers operation D.'
c2.do_d
output.txt: 実行結果
Client triggers operation A.
Component 1 does A.
Mediator reacts on A and triggers following operations:
Component 2 does C.
Client triggers operation D.
Component 2 does D.
Mediator reacts on D and triggers following operations:
Component 1 does B.
Component 2 does C.