Во-первых, в Ruby отсутствуют сигнатуры методов. Ближайшим будет проверка функции функции. Печатание утки требует мышления по-другому (слегка).
Модуль Observable - это начало, но если у вас есть требование иметь несколько событий из одного класса, этого может быть недостаточно.
Это быстрый набросок. Поддерживает методы и блоки. При необходимости измените его, чтобы адаптировать к своему коду, подходу к многопоточности и т. Д. Например, вы можете использовать method_missing, чтобы имя события было указано в имени метода, а не в качестве параметра.
class EventBase
def initialize
@listeners = Hash.new
end
def listen_event(name, *func, &p)
if p
(@listeners[name] ||= Array.new) << p
else
(@listeners[name] ||= Array.new) << func[0]
end
end
def ignore_event(name, func)
return if !@listeners.has_key?(name)
@listeners[name].delete_if { |o| o == func }
end
def trigger_event(name, *args)
return if !@listeners.has_key?(name)
@listeners[name].each { |f| f.call(*args) }
end
end
class MyClass < EventBase
def raise_event1(*args)
trigger_event(:event1, *args)
end
def raise_event2(*args)
trigger_event(:event2, *args)
end
end
class TestListener
def initialize(source)
source.listen_event(:event1, method(:event1_arrival))
source.listen_event(:event2) do |*a|
puts "event 2 arrival, args #{a}"
end
end
def event1_arrival(*a)
puts "Event 1 arrived, args #{a}"
end
end
s = MyClass.new
l = TestListener.new(s)
s.raise_event1("here is event 1")
s.raise_event2("here is event 2")