From: "Mauricio Fernández" Date: 2003-05-09T15:56:55+09:00 Subject: Re: state pattern in ruby On Fri, May 09, 2003 at 06:14:35AM +0900, ahoward wrote: > when implementing the state pattern/factory in ruby, i have used delegation > before (require 'delegate') and this works well. however, it seem like > something like this can work just as well - with faster execution times - for > simple cases: > > module M > class << self > def new args > if ... > return A.new > elsif ... > return B.new > else > return C.new > end > end > end > > private > # parent class, perhaps abstract, interface, whatever... > class M; end > > # delegate classes > class A < M; end > class B < M; end > class C < M; end > end > > allowing > > m = M.new args > > to return an A, B, or C - all supporting the methods of M::M via inheritence, > interface, abstract inheritence using NotImpliemnted, polymorphism, etc. > > > any thoughts on this? This is kinda lika the distinction between "object-based" and "class-based" in a design pattern (sorry, don't have GoF's DP at hand right now so I don't remember the exact terminology). One of the things I learned with DP is that inheritance is frequently abused and that many things should instead be done with object references. Of course, Ruby's dynamicity (?) pushes this a little bit further, because as matz once stated "I feel you're relying too much on inheritance hierarchy. In Ruby, it's at best implementation sharing." [ruby-talk:19878] But even in that example you're losing some freedom as the "state" is held by the client, and cannot be changed without his intervention; i.e., in m = M.new args the state corresponds in fact to m.class, but there's no way that is going to change as the result of different method calls to m. This comes as no surprise, because that is not the State pattern, but Abstract Factory :-) However if doing delegation this is easily (and often) done, as the state is "internal" to the object, not externalized as its class. In order to have "class-based" States, the next state could be generated as the result of every method call or Ruby would need to have #become: either m = M.new args m = m.meth arg2 m = m.meth2 arg3 or class M::A def meth ... become M::B.new # this doesn't exist in Ruby, read [ruby-talk:19673] # and around :) end end -- _ _ | |__ __ _| |_ ___ _ __ ___ __ _ _ __ | '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ | |_) | (_| | |_\__ \ | | | | | (_| | | | | |_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_| Running Debian GNU/Linux Sid (unstable) batsman dot geo at yahoo dot com * LG loves czech girls. LG: do they have additional interesting "features" other girls don't have? ;) -- #Debian