Rubyでデザインパターン
30分プログラム、その368。Rubyでデザインパターンの一部を書いてみた。
前にRubyで学ぶデザインパターンを見たときに、Rubyでデザインパターンをやるときは、Javaのをそのまま移植する必要はないなぁ、と感じたのでやってみた。
Rubyだとinterfaceやらabstractは不要なので、そのへんに気をつけてやってみた。
使い方
$ ruby dp.rb ============================== Iterator pattern ============================== Around the world in 80 days Bible Cinderela Daddy-Long-Legs ------------------------------ ============================== Adapter(継承) ============================== (Hello) *Hello* ------------------------------ ============================== Adapter(移譲) ============================== 368-dp.rb:99: warning: method redefined; discarding old initialize 368-dp.rb:103: warning: method redefined; discarding old showWithParen 368-dp.rb:107: warning: method redefined; discarding old showWithAster (__FORWARDABLE__):1: warning: method redefined; discarding old printWeak (__FORWARDABLE__):1: warning: method redefined; discarding old printStrong 368-dp.rb:118: warning: method redefined; discarding old initialize (Hello) *Hello* ------------------------------ ============================== Template Method ============================== <<HHHHH>> +-------------+ |Hello, world.| |Hello, world.| |Hello, world.| |Hello, world.| |Hello, world.| +-------------+ +------------------+ |こんにちは。| |こんにちは。| |こんにちは。| |こんにちは。| |こんにちは。| +------------------+ ------------------------------
ソースコード
#! /opt/local/bin/ruby -w # -*- mode:ruby; coding:utf-8 -*- # # dp.rb - # # Copyright(C) 2008 by mzp # Author: MIZUNO Hiroki / mzpppp at gmail dot com # http://howdyworld.org # # Timestamp: 2008/09/18 21:50:16 # # This program is free software; you can redistribute it and/or # modify it under MIT Lincence. # def section(title,&f) puts '==============================' puts title puts '==============================' f.call puts '------------------------------','' end section 'Iterator pattern' do class Book attr_reader :name def initialize(name) @name = name end end # 親クラス不要 class BookShelf def initialize(size) @books = Array.new size @last = 0 end def appendBook(book) @books[@last] = book @last += 1 end def each @books.each do|book| yield book end end end bookshelf = BookShelf.new 4 bookshelf.appendBook Book.new('Around the world in 80 days') bookshelf.appendBook Book.new('Bible') bookshelf.appendBook Book.new('Cinderela') bookshelf.appendBook Book.new('Daddy-Long-Legs') bookshelf.each{|book| puts book.name } end section 'Adapter(継承)' do class Banner def initialize(string) @string = string end def showWithParen puts "(#{@string})" end def showWithAster puts "*#{@string}*" end end # Printインタフェースが不要 class PrintBanner < Banner def initialize(string) super string end def printWeak showWithParen end def printStrong showWithAster end end # Main p = PrintBanner.new 'Hello' p.printWeak p.printStrong end section('Adapter(移譲)') do class Banner def initialize(string) @string = string end def showWithParen puts "(#{@string})" end def showWithAster puts "*#{@string}*" end end require 'forwardable' class PrintBanner extend Forwardable def_delegator :@banner, :showWithParen, :printWeak def_delegator :@banner, :showWithAster, :printStrong def initialize(string) @banner = Banner.new string end end # Main p = PrintBanner.new 'Hello' p.printWeak p.printStrong end section('Template Method')do class AbstractDisplay # Abstractは不要 def display open 5.times{ output } close end end class CharDisplay < AbstractDisplay def initialize(ch) @ch = ch end def open print '<<' end def output print @ch end def close puts '>>' end end class StringDisplay < AbstractDisplay def initialize(string) @string = string @width = string.size end def open printLine end def output puts "|#{@string}|" end def close printLine end private def printLine print '+' print '-'*@width puts '+' end end d1 = CharDisplay.new 'H' d2 = StringDisplay.new 'Hello, world.' d3 = StringDisplay.new 'こんにちは。' d1.display d2.display d3.display end