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?
-a
···
–
Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ara.t.howard@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================
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
···
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.
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
As Mauricio pointed out this is factory pattern. And I see neither need
nor advantage of tampering with “new”. The same is achieved with
module M
def M.newState …
if …
return A.new
elsif …
return B.new
else
return C.new
end
end
end
Why did you want to change “new” for this?
Another approach is to redefine methods to save the delegation instance
class Foo
def st1
def self.foo; 100; end
def self.bar; 101; end
end
def st2
def self.foo; 200; end
def self.bar; 201; end
end
end
Before you continue, go now and read… http://www.quantum-leaps.com/
Yip, I know it is a bit hype heavy and C++'ish, but his "Optimal FSM"
implementation of statecharts has some excellent ideas.
I think send(:symbol) is probably about equivalent to the C++ pointer to
method.
ie. I bet you could implement all his QP ideas in Ruby with a 1/20th the
effort. Nonetheless some of his basic concepts are very good.
Go there NOW.
···
–
John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand
This email is not designed or intended for use in on-line control of
aircraft, air traffic, aircraft navigation or aircraft communications;
or in the design, construction, operation or maintenance of any nuclear
facility.