利点
元のクラスの中身を変えずに機能を追加出来る
組み合わせで様々な機能を実現できる
欠点
小さいクラスが大量に出来る
実装サンプル
サンプル概要
HTMLの構成をDecoratorで実装します。
HTMLの表示要素となるタグと装飾要素になるタグおよびCSSをComposite=構成要素として扱います。
例えば構成要素としてDIV,MARQUEE(スライド表示する文字列),HR(横線)。
それらをタグで装飾するB,CENTERタグ。
これらを組み合わせて
- 太字でスライド表示される文字列
- 太字で背景が赤で文字が黄色のスライド表示される文字列
- センタリングされたDIV
- センタリングされた太字のDIV
- センタリングされて太字で背景が黄色で文字が赤のDIV
などを作成してみます。
登場人物
Component = WebComponent
Component = Tag
ConcreteComponent = Div
ConcreteComponent = Hr
ConcreteComponent = Marquee
Decorator = DecorateTag
ConcreteDecorator = Bold
ConcreteDecorator = Center
サンプルコード
WebComponent
# encoding: Shift_JIS =begin rdoc = WebComponentクラス =end class WebComponent # mapは各種タグ、Styleに設定が必要なパラメーターを自由に設定する attr_accessor :name,:value,:map NOT_OVERRRIDE = 'not override error' def initialize(name,value,map) @name = name @value = value @map = map end def output() raise WebComponent::NOT_OVERRRIDE end end
Tag
# encoding: Shift_JIS require_relative './web_component' =begin rdoc = Tagクラス =end class Tag < WebComponent attr_accessor :has_close_tag def initialize(name,value,map,has_close_tag) @has_close_tag = has_close_tag super(name,value,map) end def output() html = "" if @has_close_tag html << "<#{@name}>#{@value}<\/#{@name}>" else html << "<#{@name} />" end return html end end
Div
# encoding: Shift_JIS require_relative './tag' =begin rdoc = DIVタグクラス =end class Div < Tag def initialize(value,map) super("div",value,map,true) end end
Hr
# encoding: Shift_JIS require_relative './tag' =begin rdoc = HRタグクラス =end class Hr < Tag def initialize() super("hr",nil,nil,false) end end
Marquee
# encoding: Shift_JIS require_relative './tag' =begin rdoc = MARQUEEタグクラス =end class Marquee < Tag def initialize(value,map) super("marquee",value,map,true) end end
DecorateTag
# encoding: Shift_JIS require_relative './tag' =begin rdoc = DecorateTagクラス =end class DecorateTag < Tag attr_accessor :web_component def initialize(name,map,web_component) @web_component = web_component super(name,nil,map,true) end def output() html = "" html << "<#{@name}>" html << @web_component.output html << "<\/#{@name}>" return html end end
Bold
# encoding: Shift_JIS require_relative './decorate_tag' =begin rdoc = Bタグクラス =end class B < DecorateTag def initialize(map,web_component) super("b",map,web_component) end end
Center
# encoding: Shift_JIS require_relative './decorate_tag' =begin rdoc = CENTERタグクラス =end class Center < DecorateTag def initialize(map,web_component) super("center",map,web_component) end end
main
# encoding: Shift_JIS require_relative './div' require_relative './hr' require_relative './b' require_relative './marquee' require_relative './center' div_param_map = {"test"=>1} div = Div.new("divの中身",div_param_map) puts div.output marquee_param_map = {"test"=>1} marquee = Marquee.new("marqueeの中身",marquee_param_map) puts marquee.output hr = Hr.new puts hr.output b_param_map = {"test"=>1} b = B.new(b_param_map,div) puts b.output b = B.new(b_param_map,marquee) puts b.output center_param_map = {"test"=>1} center = Center.new(center_param_map,div) puts center.output center = Center.new(b_param_map,b) puts center.output
出力結果
<div>divの中身</div> <marquee>marqueeの中身</marquee> <hr /> <b><div>divの中身</div></b> <b><marquee>marqueeの中身</marquee></b> <center><div>divの中身</div></center> <center><b><marquee>marqueeの中身</marquee></b></center>