デザインパターンのうち、ProxyパターンとDecorativeパターンを使ったRubyのコード例
2022-02-01 15:24:10
プロキシパターン
要求事項
シャオミンはシャオリーに自分のためにシャオリーを追いかけてくれるように頼んだ(人形、花、チョコレートを送る)
エージェントなしのコード
# -*- encoding: utf-8 -*-
# Pursuit class
class Pursuit
attr_accessor :mm
def initialize(mm)
@mm = mm
end
def give_dolls
puts "#{mm.name} Send you dolls"
end
def give_flowers
puts "#{mm.name} send you flowers"
end
def give_chocolate
puts "#{mm.name} send you chocolates"
end
end
#The pursued class
class Girl
attr_accessor :name
def initialize(name)
@name = name
end
end
xiao_hong = Girl.new('Xiao Hong')
xiao_ming = Pursuit.new(xiao_hong)
xiao_ming.give_dolls
xiao_ming.give_flowers
xiao_ming.give_chocolate
プロキシ専用のコードです。
# -*- encoding: utf-8 -*-
# Proxy class
class Proxy
attr_accessor :mm
def initialize(mm)
@mm = mm
end
def give_dolls
puts "#{mm.name} Send you dolls"
end
def give_flowers
puts "#{mm.name} send you flowers"
end
def give_chocolate
puts "#{mm.name} send you chocolates"
end
end
#The pursued class
class Girl
attr_accessor :name
def initialize(name)
@name = name
end
end
xiao_hong = Girl.new('Xiao Hong')
xiao_ming = Proxy.new(xiao_hong)
xiao_ming.give_dolls
xiao_ming.give_flowers
xiao_ming.give_chocolate
pursuer クラスを proxy クラスに置き換えるだけです。
実際のプロキシパターンのコードです。
# -*- encoding: utf-8 -*-
# public interface module
module GiveGift
def give_dolls
end
def give_flowers
end
def give_chocolate
end
end
# Pursuit class
class Pursuit
include GiveGift
attr_accessor :mm, :name
def initialize(mm)
@mm = mm
end
def give_dolls
puts "#{mm.name} Send you dolls for #{name}"
end
def give_flowers
puts "#{mm.name} send you flowers for #{name}"
end
def give_chocolate
puts "#{mm.name} send you chocolates for #{name}"
end
end
#Proxy Class
class Proxy
include GiveGift
attr_accessor :gg
def initialize(mm)
@gg = Pursuit.new(mm)
end
def give_dolls
gg.give_dolls
end
def give_flowers
gg.give_flowers
end
def give_chocolate
gg.give_chocolate
end
end
#The pursued class
class Girl
attr_accessor :name
def initialize(name)
@name = name
end
end
xiao_hong = Girl.new('Xiao Hong')
xiao_ming = Proxy.new(xiao_hong)
xiao_ming.gg.name = '小明'
xiao_ming.give_dolls
xiao_ming.give_flowers
xiao_ming.give_chocolate
デコレーションパターン
必要条件
マッチング
コードバージョン1
# -*- encoding: utf-8 -*-
class Person
attr_accessor :name
def initialize(name)
@name = name
end
def wear_t_shirts
puts 'big t-shirt'
end
def wear_big_trouser
puts 'pants'
end
def wear_sneakers
puts 'broken sneakers'
end
def wear_suit
puts 'suit'
end
def wear_tie
puts 'tie'
end
def wear_leather_shoes
puts 'leather shoes'
end
def show
puts "***** dress up #{name}\n\n"
end
end
xc=Person.new('dish')
puts "****** first dress up"
xc.wear_t_shirts
xc.wear_big_trouser
xc.wear_sneakers
xc.show
puts "****** second_dressup"
xc.wear_suit
xc.wear_tie
xc.wear_leather_shoes
xc.show
問題は、"Superman" のコスチュームを追加する場合、Personクラスを修正しなければならず、オープンクローズの原則に違反していることです。
コードバージョン2
# -*- encoding: utf-8 -*-
class Person
attr_accessor :name
def initialize(name)
@name = name
enddef show
puts "***** dressed up as #{name}\n\n"
end
end
class Finery
def show
end
end
class TShirts < Finery
def show
puts 'big t-shirt'
end
end
class BigTrouser < Finery
def show
puts 'slacks'
end
end
class Sneakers < Finery
def show
puts 'broken sneakers'
end
end
class Suit < Finery
def show
puts 'Suit'
end
end
class Tie < Finery
def show
puts 'tie'
end
end
class LeatherShoes < Finery
def show
puts 'leather shoes'
end
end
xc = Person.new('small dish')
ts = TShirts.new
bt = BigTrouser.new
sk = Sneakers.new
puts "****** first dress"
ts.show
bt.show
sk.show
xc.show
suit = Suit.new
tie = Tie.new
ls = LeatherShoes.new
puts "****** second dress"
suit.show
tie.show
ls.show
xc.show
このように変更した結果、スーパーマンのコスチュームを追加しても、本当にPersonクラスを修正する必要はありません。問題は、様々な衣装が別々に公開され、ただ一つずつ順番に着ていくだけで、制御不能になることです。
コードバージョン3
# -*- encoding: utf-8 -*-
class Person
attr_accessor :name
def initialize(name=nil)
@name = name
end
def show
puts "***** dressed up as #{name}\n\n"
end
end
class Finery < Person
attr_accessor :componet
def decorate(componet)
@componet = componet
end
def show
componet.show if componet
end
end
class TShirts < Finery
def show
super
puts 'big t-shirt'
end
end
class BigTrouser < Finery
def show
super
puts 'collapsed pants'
end
end
class Sneakers < Finery
def show
super
puts 'broken sneakers'
end
end
class Suit < Finery
def show
super
puts 'Suit'
end
end
class Tie < Finery
def show
super
puts 'tie'
end
end
class LeatherShoes < Finery
def show
super
puts 'leather shoes'
end
end
xc = Person.new('small dish')
ts = TShirts.new
bt = BigTrouser.new
sk = Sneakers.new
puts "****** first dress"
ts.decorate xc
bt.decorate ts
sk.decorate bt
sk.show
suit = Suit.new
tie = Tie.new
ls = LeatherShoes.new
puts "****** second dress"
suit.decorate xc
tie.decorate suit
ls.decorate bt
ls.show
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン