# Multi-Module Alternative to the Factory Pattern?

**URL:** <https://www.ruby-forum.com/t/multi-module-alternative-to-the-factory-pattern/70310>\
**Category:** Ruby\
**Created:** [September 28, 2006, 3:16am UTC](https://www.ruby-forum.com/t/multi-module-alternative-to-the-factory-pattern/70310 "2006-09-28T03:16:32Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [September 28, 2006, 3:16am UTC](https://www.ruby-forum.com/t/multi-module-alternative-to-the-factory-pattern/70310/1 "2006-09-28T03:16:32Z")

</div>

I’ve been using a factory pattern for a set of packaging classes  
–classes that generate different package formats (eg. Debian, RPM,  
etc.), but it’s not quite the right fit b/c it leads to repetition of  
the staging step. Yuk! So I think a better fit is to have one class  
(Packager) that calls on external modules (or classes) for each  
different format. But, unfortuately there are quite a few attributes  
needed by each from the Packager, and it’s just doesn’t seem right to  
pass that many variables. So it seems like it would be better to just  
include the needed module into the Packager class as needed. But here  
again I can’t un-include a format module once done with it in order to  
use another format. So I’m right back to using a factory pattern.

Then I had this idea. and I’m wondering what others think of it.

First we need this little extension from Facets:

class Object

```
# Like super but skips to a specific ancestor module or class.
#
# class A
# def x ; 1 ; end
# end
#
# class B < A
# def x ; 2 ; end
# end
#
# class C < B
# def x ; superior(A) ; end
# end
#
# C.new.x #=> 1
#
def superior(klass=self.class.superclass, *args, &blk)
  unless self.class.ancestors.include?(klass)
    raise ArgumentError
  end
  called = /\`([^\']+)\'/.match(caller(1).first)[1].to_sym
  klass.instance_method(called).bind(self).call(*args,&blk)
end

```

end

Then:

module Debian  
def pack ; “Debian package”; end  
end

module RPM  
def pack ; “RPM package”; end  
end

class Packager  
include Debian, RPM

```
def pack( type )
  superior(type)
end

```

end

pkgr = Packager.new  
pkgr.pack(Debian) #=\> “Debian package”  
pkgr.pack(RPM) #=\> “RPM package”

What do you think?

Thanks,  
T.

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [September 28, 2006, 4:05pm UTC](https://www.ruby-forum.com/t/multi-module-alternative-to-the-factory-pattern/70310/2 "2006-09-28T16:05:58Z")

</div>

Trans schrieb:

> I’ve been using a factory pattern for a set of packaging classes  
> –classes that generate different package formats (eg. Debian, RPM,  
> etc.), but it’s not quite the right fit b/c it leads to repetition of  
> the staging step. Yuk! So I think a better fit is to have one class  
> (Packager) that calls on external modules (or classes) for each  
> different format. But, unfortuately there are quite a few attributes  
> needed by each from the Packager, and it’s just doesn’t seem right to  
> pass that many variables. (…)

Tom, couldn’t you pass the packager itself to the external modules and  
let them query the attributes they need?

Regards,  
Pit

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [September 28, 2006, 4:56pm UTC](https://www.ruby-forum.com/t/multi-module-alternative-to-the-factory-pattern/70310/3 "2006-09-28T16:56:17Z")

</div>

Hi Pit–

Pit C. wrote:

> Tom, couldn’t you pass the packager itself to the external modules and  
> let them query the attributes they need?

Yes. That would work too. And that might be the best way to do it.  
Though it still means writing code to do the attribute transfer, but  
that can be automated fairly easily.

I’m still curious about this “multi-module” idea in general though.  
Seems like it could be an alternative to code injection too.

T.

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [September 28, 2006, 5:26pm UTC](https://www.ruby-forum.com/t/multi-module-alternative-to-the-factory-pattern/70310/4 "2006-09-28T17:26:24Z")

</div>

On Thu, 28 Sep 2006, Trans wrote:

> I’m still curious about this “multi-module” idea in general though.  
> Seems like it could be an alternative to code injection too.
> 
> T.

why not:

```
 harp:~ > cat a.rb
 module DEB
   A, B, C = %w( D E B )
   def self.pack_step_one() p A end
   def self.pack_step_two() p B end
   def self.pack_step_three() p C end
   def self.pack_step_four(arg) p arg end
 end

 module RPM
   A, B, C = %w( R P M )
   def self.pack_step_one() p A end
   def self.pack_step_two() p B end
   def self.pack_step_three() p C end
   def self.pack_step_four(arg) p arg end
 end

 class Packager
   def initialize type
     @type = type
   end
   def pack arg
     @type.instance_eval{
       pack_step_one
       pack_step_two
       pack_step_three
       pack_step_four arg
     }
   end
 end

 packager = Packager.new DEB
 packager.pack 42

 harp:~ > ruby a.rb
 "D"
 "E"
 "B"
 42

```

??

btw. for these kinds of setups: modules with state (singletons) i’ve  
been  
using prototypes lately:

```
 harp:~ > cat a.rb
 require 'prototype'

 DEB = prototype{
   @a, @b, @c = %w( D E B )
   def pack_step_one() p @a end
   def pack_step_two() p @b end
   def pack_step_three() p @c end
   def pack_step_four(arg) p arg end
 }

 RPM = prototype{
   @a, @b, @c = %w( D E B )
   def pack_step_one() p @a end
   def pack_step_two() p @b end
   def pack_step_three() p @c end
   def pack_step_four(arg) p arg end
 }

 class Packager
   attr 'type'
   def initialize type
     @type = type
   end
   def pack arg
     @type.instance_eval{
       pack_step_one
       pack_step_two
       pack_step_three
       pack_step_four arg
     }
   end
 end

 packager = Packager.new DEB
 packager.pack 42

 harp:~ > ruby -r rubygems a.rb
 "D"
 "E"
 "B"
 42

```

i guess i’m failing to see what multi-module inclusion givs you that  
delegation  
plus argument passing (into the delegate module not the other way  
around)  
doesn’t?

regards.

-a

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [September 28, 2006, 7:47pm UTC](https://www.ruby-forum.com/t/multi-module-alternative-to-the-factory-pattern/70310/5 "2006-09-28T19:47:09Z")

</div>

removed\_email\_address@domain.invalid wrote:

> why not:  
> [snip]

Only becuase there are a lot of arguments to pass.

> btw. for these kinds of setups: modules with state (singletons) i’ve been  
> using prototypes lately:

Right on. I do like the prototype stuff. Just don’t have the time to  
invest init at them moment though.

[snip cool example use of prototype]

> i guess i’m failing to see what multi-module inclusion givs you that delegation  
> plus argument passing (into the delegate module not the other way around)  
> doesn’t?

The advantage is access to the internal state --no passing of  
attributes required. Esspecailly true when you have alot of  
attributes/arguments involved. Simple example:

```
 require 'facet/kernel/as'

 module DEB
   A, B, C = %w( D E B )
   def pack_step_one() p A+a end
   def pack_step_two() p B+b end
   def pack_step_three() p C+c end
 end

 module RPM
   A, B, C = %w( R P M )
   def pack_step_one() p A+a+b+c end
   def pack_step_two() p B+b+c+a end
   def pack_step_three() p C+c+a+b end
 end

 class Packager
   include DEB, RPM
   attr :a,:b,:c
   def initialize
     @a,@b,@c = %w{ 1 2 3 }
   end
   def pack type
     as(type).pack_step_one
     as(type).pack_step_two
     as(type).pack_step_three
   end
 end

 packager = Packager.new
 packager.pack DEB, 42

 harp:~ > ruby a.rb
 "D123"
 "E231"
 "B312"
 42

```

Note #as works like #superior from my last example but uses magic-dot  
notation to allow any method to be called. (It would be nice if it took  
a block but I’ll have to work on that).

T.

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [September 28, 2006, 8:17pm UTC](https://www.ruby-forum.com/t/multi-module-alternative-to-the-factory-pattern/70310/6 "2006-09-28T20:17:13Z")

</div>

On Fri, 29 Sep 2006, Trans wrote:

> Only becuase there are a lot of arguments to pass.

hash? array?

> ```
> module DEB
> def pack_step_three() p C+c+a+b end
> as(type).pack_step_two
> "B312"
> 42
> 
> ```
> 
> Note #as works like #superior from my last example but uses magic-dot  
> notation to allow any method to be called. (It would be nice if it took a  
> block but I’ll have to work on that).

hmm. how bout this:

```
 harp:~ > cat a.rb
 class Object
   def including m, &b
     (class << (d=dup); self; end).module_eval{ include m }
     d.instance_eval &b
   end
 end

 module DEB
   A, B, C = %w( D E B )
   def pack_step_one() p A+a end
   def pack_step_two() p B+b end
   def pack_step_three() p C+c end
 end

 module RPM
   A, B, C = %w( R P M )
   def pack_step_one() p A+a+b+c end
   def pack_step_two() p B+b+c+a end
   def pack_step_three() p C+c+a+b end
 end

 class Packager
   [:a,:b,:c].each{|a| attr a}

   def initialize
     @a,@b,@c = %w{ 1 2 3 }
   end

   def pack type, *a
     including(type){
       pack_step_one
       pack_step_two
       pack_step_three
     }
   end
 end

 packager = Packager.new
 packager.pack DEB, 42

 harp:~ > ruby a.rb
 "D1"
 "E2"
 "B3"

```

sure the performance will suck though ;-(

fun stuff…

i like your ‘as’ method.

-a
