Hatena::Groupruby

kdmsnrの日記

1000-01-12

Singleton

18:31

class Single
  @@instance = Single.new
  def self.instance
    return @@instance
  end
end

p Single.instance #<Single:0x2bb67bc> 同じ
p Single.instance #<Single:0x2bb67bc> 同じ
p Single.new #<Single:0x2bb5d44> 違う

#-------------------------------------------

require 'singleton'
class Single
  include Singleton
end

p Single.instance #<Single:0x2ba7294> 同じ
p Single.instance #<Single:0x2ba7294> 同じ
p Single.new # private method `new' called for Single:Class (NoMethodError)

1000-01-05

Observer

12:41

class Employee
  def initialize(salary)
    @salary = salary
  end
  
  def update_salary=(new_salary)
    @salary = new_salary
      # ここで通知しないと!
      notify_observer
  end

  attr_accessor :observer
  def notify_observer
    # @observerが複数になってもOK
    @observer.update(self)  
  end
end

それObservableモジュールで(ry

13:02

require 'observer'

class Employee
  include Observable # オブザーバを扱うためのメソッドが用意されてる

  attr_accessor :salary
  def update_salary new_salary
    @salary = new_salary
    changed # フラグ変更ktkr
    notify_observers(self) # みんなに通知する
  end
end

# こいつらオブザーバ
class PayrollDepartment
  def update emp
    puts emp.salary
  end
end

class PayrollDepartment2
  def update emp
    puts emp.salary
  end
end

class PayrollDepartment3
  def update emp
    puts emp.salary
  end
end

emp = Employee.new
emp.add_observer(PayrollDepartment.new) # オブザーバ追加用のメソッドもある
emp.add_observer(PayrollDepartment2.new)
emp.add_observer(PayrollDepartment3.new)
emp.update_salary 100

1000-01-04

Strategy

12:02

class Report
  attr_reader :title, :text
  attr_accessor :formatter

  def initialize(formatter)
    @title = 'Monthly Report'
    @text =  [ 'Things are going', 'really, really well.' ]
    @formatter = formatter
  end

  def output_report
    @formatter.output_report( @title, @text )
  end
end

## クライアント
report = Report.new(HTMLFormatter.new)
report.output_report

# 途中で切り替えたり
report.formatter = PlainTextFormatter.new
report.output_report

それ、Procでできるよ

12:02

class Report
  attr_reader :title, :text
  attr_accessor :formatter

  def initialize(&formatter)
    @title = 'Monthly Report'
    @text =  [ 'Things are going', 'really, really well.' ]
    @formatter = formatter
  end

  def output_report
    @formatter.call( self )
  end
end

おさらい

def target(&block) # ブロックをProcで受けますよ
  p block # Procオブジェクト
end

# ブロック付きで呼び出し
target do |i| 
  #
end

# Procをブロックにして呼び出し
target(&Proc.new{})

# --------------------------

def target(proc)
  p proc # 当然Procオブジェクト
end

target(Proc.new{})

#---------------

def target # 引数を明示しないでブロック受け
  yield
end

target do ||
  puts "hoge"
end

1000-01-03

Template Method

11:28

class Report
  def initialize
    @title = 'Monthly Report'
    @text =  ['Things are going', 'really, really well.']
  end

  # テンプレートメソッド  -- 呼び出し順が決まってる
  def output_report
    output_head
    output_body
    output_foot
  end

  # 実装しないとダメ
  def outputbody
    raise 'Called abstract method: output_head'
  end

  # してもしなくてもOK -- フックメソッド
  def output_head
  end

  def output_foot
  end
end

class HTMLReport < Report
  #...
end

class PlainTextReport < Report
  #...
end

# クライアント
HTMLReport.new.output_report
PlainTextReport.new.output_report

実例

11:28

require 'webrick'

class HelloServer < WEBrick::GenericServer
  def run(socket)
    socket.print('Hello TCP/IP world')
  end
end
run(sock) -> ()
クライアントと接続された TCPSocket オブジェクトを引数として呼ばれ、具体的な処理を行います。 WEBrick::GenericServer のサブクラスはこのメソッドを適切に再定義しなければいけません。