Forum: Ruby Is this a kind of design patterns?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ca0b18ec9e11dc777b2b8084fe5d5f90?d=identicon&s=25 Sam Kong (Guest)
on 2006-03-22 08:18
(Received via mailing list)
Hi!

Sometimes a class provides object instantiation methods other than new.
See an example.

class Color
    def initialize r, g, b
        @r = r
        @g = g
        @b = b
    end

    def to_s
        "R: #{@r}, G: #{@g}, B: #{@b}"
    end

    class << self
        def red
            new 255, 0, 0
        end

        def blue
            new 0, 0, 255
        end

        def green
            new 0, 255, 0
        end
    end
end

puts Color.new(100, 120, 140)
puts Color.red
puts Color.blue


Is this one of design patterns, or just a simple idiom?
It's similar to a factory method pattern but it's not according to the
definition.
Is there any name for it?

TIA.

Sam
8aaafaf40d3dc025f7df2e52c5facc23?d=identicon&s=25 killy-kun (Guest)
on 2006-03-22 09:49
(Received via mailing list)
Sam Kong wrote:
>     end
>         def blue
> puts Color.red
> Sam
>

isn't that the facory design pattern ?
Bd0203dc8478deb969d72f52e741bd4f?d=identicon&s=25 Daniel Baird (Guest)
on 2006-03-22 10:35
(Received via mailing list)
The truth is, as a ganeral rule the original G4 design patterns were
kinda
statically-typed-language-centric, so it wouldn't surprise me if there
was
some small details in Ruby versions of the patterns that didn't quite
fit
the "classic" description.

In this case though, it does look a lot like the Factory pattern, apart
from
new still being available.  I think if Color.new was re-declared as
private,
that would make it a textbook case of the Factory pattern.

IANA(language)L though..

;Daniel

On 22/03/06, killy-kun <killy-kun@wanadoo.fr> wrote:
> >         @g = g
> >         end
> >
> > TIA.
> >
> > Sam
> >
>
> isn't that the facory design pattern ?
>
>


--
Daniel Baird
http://danielbaird.com (TiddlyW;nks! :: Whiteboard Koala :: Blog ::
Things
That Suck)
[[My webhost uptime is ~ 92%.. if no answer pls call again later!]]
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-03-22 14:24
(Received via mailing list)
Sam Kong wrote:
>     end
>         def blue
> puts Color.red
> puts Color.blue
>
>
> Is this one of design patterns, or just a simple idiom?
> It's similar to a factory method pattern but it's not according to the
> definition.
> Is there any name for it?

Since you invoke a class's method "new" like any other method of any
other object (no special syntax) you can say with some justification
that all classes are basically factories.

IMHO your example is not optimal because it wastes resources.  Since
Color is immutable anyway constants seem a better choice:

Color = Struct.new :r, :g, :b
class Color
   def to_s
     sprintf "R: 0x%02x, G: 0x%02x, B: 0x%02x", self.r, self.g, self.b
   end

   RED   = new 0xFF, 0x00, 0x00
   BLUE  = new 0x00, 0x00, 0xFF
   GREEN = new 0x00, 0xFF, 0x00
end

Kind regards

	robert
25e11a00a89683f7e01e425a1a6e305c?d=identicon&s=25 Wilson Bilkovich (Guest)
on 2006-03-22 15:14
(Received via mailing list)
On 3/22/06, Sam Kong <sam.s.kong@gmail.com> wrote:
>     end
>         def blue
> puts Color.red
> puts Color.blue
>
>
> Is this one of design patterns, or just a simple idiom?
> It's similar to a factory method pattern but it's not according to the
> definition.
> Is there any name for it?
>

That's the "Factory Method" pattern.  It's handy when you want
SomeClass.new to return an instance of SomeOtherClass, or just when
you want things to be easier to read.

One of my favorite examples (I think this is a Martin Fowler trick) is:
some_date = december(10,2006)
Ca0b18ec9e11dc777b2b8084fe5d5f90?d=identicon&s=25 Sam Kong (Guest)
on 2006-03-22 17:54
(Received via mailing list)
Wilson Bilkovich wrote:
> That's the "Factory Method" pattern.  It's handy when you want
> SomeClass.new to return an instance of SomeOtherClass, or just when
> you want things to be easier to read.
>
> One of my favorite examples (I think this is a Martin Fowler trick) is:
> some_date = december(10,2006)

At first I thought so.
But the definition of "Factory Method Pattern" bothered me.
The definition of "Factory Method Pattern" is:

"Define an interface for creating an object, but let subclasses decide
which class to instantiate. Factory Method lets a class defer
instantiation to subclasses. "

However, in my Color example, there's no subclassing involved.
So the class itself is a factory as well as the product that the
factory makes.
Do you think that we can still call it "Factory Method Pattern"?

Sam
Ca0b18ec9e11dc777b2b8084fe5d5f90?d=identicon&s=25 Sam Kong (Guest)
on 2006-03-22 18:05
(Received via mailing list)
Robert Klemme wrote:
> >         @b = b
> >
> > puts Color.new(100, 120, 140)
> other object (no special syntax) you can say with some justification
>
>    RED   = new 0xFF, 0x00, 0x00
>    BLUE  = new 0x00, 0x00, 0xFF
>    GREEN = new 0x00, 0xFF, 0x00
> end

This looks tricky and wonderful.
I just tried to make a simple example which was not intended to be
ooptimal.
I will apply your way when I need to make a real code.:-)
Thank you.

Sam
36958dd94ca666a38483df282a5214d5?d=identicon&s=25 Peter Ertl (Guest)
on 2006-03-22 18:14
(Received via mailing list)
my personal definition:

factory method:
  method, that creates a object,
  because new(...) is not sufficient
  in that case

imho there's too much babbling about design patterns und too
little pragmatism. who cares if it's pattern #1 or pattern #2.

it's more a matter of good taste as a matter of applying rules.

especially in java I have seen ridiculous numbers of classes doing
trivial stuff using factories, abstract classes, interfaces, proxies,
adapters, delegates and the like. it's often considered by so called
architects to be good software if it uses several design pattern
no matter what for...
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-03-22 19:31
Robert Klemme wrote:
> Sam Kong wrote:
>>     end
>>         def blue
>> puts Color.red
>> puts Color.blue
>>
>>
>> Is this one of design patterns, or just a simple idiom?
>> It's similar to a factory method pattern but it's not according to the
>> definition.
>> Is there any name for it?
>
> Since you invoke a class's method "new" like any other method of any
> other object (no special syntax) you can say with some justification
> that all classes are basically factories.
>
> IMHO your example is not optimal because it wastes resources.  Since
> Color is immutable anyway constants seem a better choice:
>
> Color = Struct.new :r, :g, :b
> class Color
>    def to_s
>      sprintf "R: 0x%02x, G: 0x%02x, B: 0x%02x", self.r, self.g, self.b
>    end
>
>    RED   = new 0xFF, 0x00, 0x00
>    BLUE  = new 0x00, 0x00, 0xFF
>    GREEN = new 0x00, 0xFF, 0x00
> end

I was thinking along the same lines, but I do like the method interface
(e.g. Color.red over Color::RED).  My suggestion would have been
something like:

  class Color
    ...
    class << self
      def red
        @red ||= new 255, 0, 0
      end
      ...
    end
  end

--
-- Jim Weirich
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-03-22 19:36
Peter Ertl wrote:
> imho there's too much babbling about design patterns und too
> little pragmatism. who cares if it's pattern #1 or pattern #2.

The value of patterns is the vocabulary it gives to developers.

> it's more a matter of good taste as a matter of applying rules.
>
> especially in java I have seen ridiculous numbers of classes doing
> trivial stuff using factories, abstract classes, interfaces, proxies,
> adapters, delegates and the like. it's often considered by so called
> architects to be good software if it uses several design pattern
> no matter what for...

Ahh, now this I agree with.  People get it in their heads that patterns
are good, what they forget is that every pattern solves a given problem
with a set of tradeoffs.  Understanding the tradeoffs is crucial to
fully understanding the pattern.  Too many people blindly apply the full
blown pattern right out of the GOF book without considering the costs.

Beware of programmers who have just learned a new pattern and are
looking for a place to apply it.

--
-- Jim Weirich
Ca0b18ec9e11dc777b2b8084fe5d5f90?d=identicon&s=25 Sam Kong (Guest)
on 2006-03-22 19:38
(Received via mailing list)
Peter Ertl wrote:
> it's more a matter of good taste as a matter of applying rules.
>
> especially in java I have seen ridiculous numbers of classes doing
> trivial stuff using factories, abstract classes, interfaces, proxies,
> adapters, delegates and the like. it's often considered by so called
> architects to be good software if it uses several design pattern
> no matter what for...

You may be right.
However, knowing the right definition is important for communcation.
If somebody tells you to make a class using "X" pattern, you need to
understand what "X" pattern means.
The pattern names might have been arbitrarily made but now it's very
common almost like a standard.

Sam
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-03-22 19:42
Wilson Bilkovich wrote:
> On 3/22/06, Sam Kong <sam.s.kong@gmail.com> wrote:
>> Is this one of design patterns, or just a simple idiom? [...]
>
> That's the "Factory Method" pattern.  It's handy when you want
> SomeClass.new to return an instance of SomeOtherClass, or just when
> you want things to be easier to read.

Hmmm ... It's not the GOF Factory Method pattern.  It doesn't even solve
the same problem that the Factory Method pattern is designed to address.

But it is a useful technique ... pattern or not.

--
-- Jim Weirich
52a177e9dbd3e614825aabc4e45f8cd6?d=identicon&s=25 Mark Volkmann (Guest)
on 2006-03-22 20:50
(Received via mailing list)
On 3/22/06, Jim Weirich <jim@weirichhouse.org> wrote:
>   end
Is there any difference between the above code and this?

   class Color
     ...
     def self.red
         @red ||= new 255, 0, 0
     end
     ...
   end
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-22 22:17
(Received via mailing list)
Jim Weirich wrote:
>>> definition.
>>    def to_s
> something like:
>
>   class Color
>     ...
>     class << self
>       def red
>         @red ||= new 255, 0, 0
>       end
>       ...
>     end
>   end

And this is tantamount to dependency injection. For example, with my
mindi framework (findable on RAA), there is the
examples/color-namespace.rb:

require 'mindi'

class PictureApp
  include MinDI::InjectableContainer

  class Picture
    attr_reader :opts
    def initialize(opts)
      @opts = opts
    end
  end

  class Color < Struct.new(:r, :g, :b)
    def +(color)
      Color.new(r + color.r, g + color.g, b + color.b)
    end
  end

  class ColorNamespace
    include MinDI::InjectableContainer

    red     { Color.new(1,0,0) }
    green   { Color.new(0,1,0) }
    yellow  { red + green      }
  end

  colors  { ColorNamespace.new }
  picture { Picture.new(:background => colors.yellow) }
end

pic_app = PictureApp.new
pic = pic_app.picture
raise unless pic.opts[:background] == pic_app.colors.yellow
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-03-23 10:14
(Received via mailing list)
Jim Weirich wrote:
>>> definition.
>>    def to_s
> something like:
>
>   class Color
>     ...
>     class << self
>       def red
>         @red ||= new 255, 0, 0
>       end
>       ...
>     end
>   end

IMHO this is not thread safe.  If you need the method interface, you
could do something like

class Color
   def self.method_missing(s,*a,&b)
     if a.empty? && b.nil?
       const_get s.to_s.upcase
     else
       super
     end
   end
end

:-)

	robert
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2006-03-23 10:29
(Received via mailing list)
let us wrap
const_get

begin
    const_get(...)
rescue NameError
   super(...)
end
 in order to get NoMethodError instead of a NameError

Cheers
Robert
On 3/23/06, Robert Klemme <bob.news@gmx.net> wrote:
> >>> Is this one of design patterns, or just a simple idiom?
> >> Color = Struct.new :r, :g, :b
> > I was thinking along the same lines, but I do like the method interface
> >     end
>        super
>      end
>    end
> end
>
> :-)
>
>         robert
>
>
>


--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-03-23 14:23
Robert Klemme wrote:
> IMHO this is not thread safe.  If you need the method interface, you
> could do something like
[...]
> :-)

I did catch the smiley.  :)

Given that the original returned a new object on every invocation, a
race condition that might generate an extra light weight object or two
at initialization seems to be a low risk.

However, if I were really concerned about the race condition, I think I
would go the metaprogramming route rather then the dynamic lookup route.
Something more like this:

  class Color
    ...
    class << self
      private
      def define(name, color)
        class_eval "#{name.to_s.upcase} = color"
        class_eval "def Color.#{name}; #{name.to_s.upcase}; end"
      end
    end

    define :red, Color.new(255, 0, 0)
    ...
  end

;)

--
-- Jim Weirich
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2006-03-23 14:36
(Received via mailing list)
On 3/22/06, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:
> >       ...
>      ...
>    end


 No, not at my knowledge

--
> R. Mark Volkmann
> Object Computing, Inc.
>
>


--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-03-23 14:48
(Received via mailing list)
Jim Weirich wrote:
> Robert Klemme wrote:
>> IMHO this is not thread safe.  If you need the method interface, you
>> could do something like
> [...]
>> :-)
>
> I did catch the smiley.  :)

:-)

>     class << self
>
> ;)

:-)

Since we're in Color anyway, you can simplify the definition that by

   class Color
     # ...
     class << self
       private
       def define(name, *args)
         cname = name.to_s.upcase
         col = const_set( cname, new(*args))
         class_eval "def self.#{name}; #{cname}; end"
       end
     end

     define :red, 255, 0, 0
     # ...
   end

:-)

Kind regards

	robert
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-03-23 17:13
Robert Klemme wrote:
> Since we're in Color anyway, you can simplify the definition that by

I like that.

And I love the collective refactoring that goes on in this list!

--
-- Jim Weirich
36958dd94ca666a38483df282a5214d5?d=identicon&s=25 Peter Ertl (Guest)
on 2006-03-23 17:39
(Received via mailing list)
I got great improvements to make color usage enterprise ready...

Here comes my first class color object using state-of-the-art
design patterns for better scalability and performance

I was designed using the rational design process + UML

class ColorRegistry
private

  def self.mix(*colors)
    r,g,b=[0,0,0]
    while color = colors.shift
      r += color[0]
      g += color[1]
      b += color[2]
    end
    [r,g,b]
  end

  RED   = [255,0,0]
  GREEN = [0,0b11111111,0]
  BLUE  = [0,0,0xff]
  WHITE = mix(RED, GREEN, BLUE)
  YELLOW = mix(RED, GREEN)
  # more to come

public
  def self.get_binding
    binding
  end

end


class ColorEvaluator
  def self.get(name)
    eval(name.upcase, ColorRegistry.get_binding)
  end
end

puts ColorEvaluator.get("yellow")
puts ColorEvaluator.get("red")
puts ColorEvaluator.get("white")
5810a1b7743eb2186ca0ea1d0a3469a0?d=identicon&s=25 Stephen Bannasch (Guest)
on 2006-03-23 22:31
(Received via mailing list)
I have a bunch of template documents which I need to manipulate in
very simple ways. I'd like to be able to insert Ruby variables into
the template. Here is a very short example:

file fruit_template.txt: This is a fruit: #{fruit}.

fruit = "apple"
f = IO.read("fruit_template.txt")

Then somehow I'd like to end up with this string:
"This is a fruit: apple."

This works fine of course if I construct the string in Ruby:
s = "This is a fruit: #{fruit}."
=> "This is a fruit: apple."

Thanks for any advice.
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-23 23:13
(Received via mailing list)
On Mar 23, 2006, at 3:31 PM, Stephen Bannasch wrote:

> "This is a fruit: apple."
The easy answer to your question is to use eval():

 >> fruit = "apple"
=> "apple"
 >> f = 'This is a fruit: #{fruit}.'
=> "This is a fruit: \#{fruit}."
 >> eval %Q{"#{f}"}
=> "This is a fruit: apple."

The right answer is to use a template library, like the standard ERB:

 >> f = "This is a fruit:  <%= fruit %>."
=> "This is a fruit:  <%= fruit %>."
 >> require "erb"
=> true
 >> ERB.new(f).result(binding)
=> "This is a fruit:  apple."

Hope that helps.

James Edward Gray II
This topic is locked and can not be replied to.