最近讀書會在讀深入淺出設計模式,趁這個機會複習一下設計模式,試著舉出簡單的例子並且用非模式與模式的方式來實作,比較它們的差異與優缺點。
我們有三個class分別為 鴨子(Duck)、
企鵝(Penguin)、
小雞(Chicken),它們各自擁有不同的飛行(fly)與游泳(swim)的行為如下:
在建立上面三種鳥的 instance 時,每個 instance 必須要有 who, fly, swim 的 method 並會印出對應的行為。
class Bird
def who
"I\'m a #{self.class}."
end
def fly
fail 'You should implement "fly" method in Bird-based class.'
end
def swim
fail 'You should implement "swim" method in Bird-based class.'
end
end
class Duck < Bird
def fly
'I can fly.'
end
def swim
'I can swim.'
end
end
class Penguin < Bird
def fly
'I cannot fly.'
end
def swim
'I can swim very fast.'
end
end
class Chicken < Bird
def fly
'I cannot fly.'
end
def swim
'I cannot swim.'
end
end
duck = Duck.new
p duck.who # "I'm a Duck."
p duck.fly # "I can fly."
p duck.swim # "I can swim."
penguin = Penguin.new
p penguin.who # "I'm a Penguin."
p penguin.fly # "I cannot fly."
p penguin.swim # "I can swim very fast."
chicken = Chicken.new
p chicken.who # "I'm a Chicken."
p chicken.fly # "I cannot fly."
p chicken.swim # "I cannot swim."
module FlyBehavior
class Base
def fly
fail 'You should implement "fly" method in FlyBehavior-based class.'
end
end
class CannotFly < FlyBehavior::Base
def fly
'I cannot fly.'
end
end
class CanFly < FlyBehavior::Base
def fly
'I can fly.'
end
end
end
module SwimBehavior
class Base
def swim
fail 'You should implement "swim" method in SwimBehavior-based class.'
end
end
class CannotSwim < SwimBehavior::Base
def swim
'I cannot swim.'
end
end
class CanSwim < SwimBehavior::Base
def swim
'I can swim.'
end
end
class SwimFast < SwimBehavior::Base
def swim
'I can swim very fast.'
end
end
end
class Bird
def initialize(fly_behavior, swim_behavior)
@fly_behavior = fly_behavior
@swim_behavior = swim_behavior
end
def who
"I'm a #{self.class}."
end
def fly
@fly_behavior.fly
end
def swim
@swim_behavior.swim
end
end
class Duck < Bird
def initialize
super(FlyBehavior::CanFly.new, SwimBehavior::CanSwim.new)
end
end
class Penguin < Bird
def initialize
super(FlyBehavior::CannotFly.new, SwimBehavior::SwimFast.new)
end
end
class Chicken < Bird
def initialize
super(FlyBehavior::CannotFly.new, SwimBehavior::CannotSwim.new)
end
end
duck = Duck.new
p duck.who # "I'm a Duck."
p duck.fly # "I can fly."
p duck.swim # "I can swim."
penguin = Penguin.new
p penguin.who # "I'm a Penguin."
p penguin.fly # "I cannot fly."
p penguin.swim # "I can swim very fast."
chicken = Chicken.new
p chicken.who # "I'm a Chicken."
p chicken.fly # "I cannot fly."
p chicken.swim # "I cannot swim."
Strategy - 策略模式
將 class 的行為(例如:fly, swim)封裝成一系列的 class(FlyBehavoir, SwimBehavior) ,讓其它的 class(Duck, Penguin, Chicken) 藉由這些 class(FlyBehavoir, SwimBehavior) 而擁有這些行為,使行為可以動態的切換或變動而不會影響原本包含這些行為的 class(Duck, Penguin, Chicken)。
當多個 class 都擁有類似的行為,而這些行為可能需要動態的變更,則這些行為(變動的部分)就應該要抽離出來。