最近讀書會在讀深入淺出設計模式,趁這個機會複習一下設計模式,試著舉出簡單的例子並且用非模式與模式的方式來實作,比較它們的差異與優缺點。
我們有一個訊息轉發系統(MessageDeliver),它會接收傳入訊息並轉發給其它三個系統:螢幕顯示系統(ScreenDisplay)、列印系統(Printer)與寄信系統(Mailer)。其中每個系統有下列的行為:
class ScreenDisplay
def display(msg)
"The message '#{msg}' is displayed on the screen."
end
end
class Printer
def print(msg)
"The message '#{msg}' is printed."
end
end
class Mailer
def mail(msg)
"The message '#{msg}' is mailed."
end
end
class MessageDeliver
def initialize(screen_display, printer, mailer)
@screen_display = screen_display
@printer = printer
@mailer = mailer
end
def deliver(msg)
@screen_display.display(msg)
@printer.print(msg)
@mailer.mail(msg)
end
end
screen_display = ScreenDisplay.new
printer = Printer.new
mailer = Mailer.new
msg_deliver = MessageDeliver.new(screen_display, printer, mailer)
msg_deliver.deliver('Hello')
module Observer
def update(msg)
fail 'You should implement "update" in your Observer-based class'
end
end
class ScreenDisplay
include Observer
def display(msg)
"The message '#{msg}' is displayed on the screen."
end
def update(msg)
display(msg)
end
end
class Printer
include Observer
def print(msg)
"The message '#{msg}' is printed."
end
def update(msg)
print(msg)
end
end
class Mailer
include Observer
def mail(msg)
"The message '#{msg}' is mailed."
end
def update(msg)
mail(msg)
end
end
class MessageDeliver
def initialize
@observers = []
end
def attach(observer)
@observers.push(observer)
end
def deliver(msg)
@observers.each do |observer|
observer.update(msg)
end
end
def detach(observer)
@observers.delete(observer)
end
end
screen_display = ScreenDisplay.new
printer = Printer.new
mailer = Mailer.new
msg_deliver = MessageDeliver.new
msg_deliver.attach(screen_display)
msg_deliver.attach(printer)
msg_deliver.attach(mailer)
msg_deliver.deliver('Hello')
msg_deliver.detach(printer)
msg_deliver.deliver('Hi')
Observer - 觀察者模式
當主題(subject) class(MessageDeliver)有變動時,需要通知其它的觀察者(observer) class(ScreenDisplay, Printer, Mailer)去做對應的事情時,可以在主題 class中記錄(@observer)有哪些觀察者 class 已經有註冊(attach),利用 attach 與 detach method 來註冊或移除觀察者,就可以做到變動時的通知,同時也可以動態增減通知的對象。
當某個主題 class 變動時需要通知其它觀察者 class,而且有可能需要動態增減通知的對象。