From: Hideto ISHIBASHI Date: 2000-04-26T00:32:26+09:00 Subject: [ruby-list:22122] Re: shell interactive 石橋秀仁です。 > こんにちは、時田です。 > > だから、Decoratorパターンなんですよ。JavaのStream系と同じ。 > > でも、ぼく自身は必要性を感じません。上記のようにmix-inで済むから。 > > Javaを知らないから Decoratorパターンってのが、よくわからないんですよね(^^; > いや、「これがそーだっ」ってのは printf のすげ替えでなんとなくわかるんですけど > 「だから、Decoratorパターンなんですよ」って事は、単なるすげ替えとは > 違うって事ですよね? > 手法でなく、どういう思想のものなのかだけ教えてもらえますか? > つまり、マクロアセンブラでいう所のマクロ的なプリプロセッサによるすげ替え > との違いを簡単にで構わないので(^^; たしかに、"alias print_old print"というのは、 われながら気持ちわるいです (^^; だから、もうすこし工夫して、 * 継承してsuperを呼ぶ * Decoratorパターンを使う というのを考えました。(で、Decoratorについては説明しませんでしたね) まず、やみくもに継承するのはOOPL初心者のC++ユーザがやりがちで、 一番よくない。次に、いちおうdelegate.rbのDelegate(Proxy)でも 解決できますが、もう一声ほしいところです。 そこで、Decoratorパターン (別名Wrapper) というのが出てきます。 「オブジェクトに動的に責任を追加する」。具体的には、あるクラスに 機能を追加したいときに、「透明」なクラスを「かぶせる (ラップする)」。 「透明」とは、「インターフェースを変更しない」という意味。 つまり、もとのクラスと全く同じように使える。 たとえば、 class Foo def initialize(foo) @foo = foo end attr :foo def bar print foo end end class FooWrapper def initialize(obj) @obj = obj end def foo @obj.foo end def bar print "foo = ", @obj.foo, "\n" end end foo = Foo.new("test") foo.bar # => "test" wrapped_foo = FooWrapper.new(foo) wrapped_foo.bar # => "foo = test\n" このコードで、Foo (foo)とFooWrapper (wrapped_foo)は、 同じメッセージを受けつけます。インターフェースだけでは 見分けがつきませんね?これを「透明」といいます。 で、ちょうどいいときに、前田さんのメールがありました。 From: Shugo Maeda Subject: [ruby-list:22096] libwrap-ruby > 前田です。 > require "tcpd" > > serv = TCPServer.open(ARGV.shift || "echo") > tcpd = TCPWrapper.new("echod", serv, true, 30) > loop do > ns = tcpd.accept > Thread.start do > s = ns > while line = s.gets > s.print(line) > end > s.shutdown > s.close > end > end 既存のクラス (IOやらSocketやら) に手をつけずに、 こういう拡張ができるところがDecoratorの利点ですね :) -- Hideto "rubyholic" ISHIBASHI