From: Woody Peterson Date: 2010-09-18T05:39:31+09:00 Subject: composition vs 'leaf-class mixins' (vs class inheritance) I have a design question inspired by Rails 3 internals. In Design Patterns in Ruby, the Strategy pattern is cited as a way to vary an algorithm following the oft-spoken "prefer composition over inheritance" advice. For a concrete example, let's say we wanted to fight in the matrix: class Person attr_accessor :skills def initialize(skills) @skills = skills end def fight @skills.each { |skill| skill.invoke } end end class KungFu def invoke puts "5-fisted punch" end end class Dodge def invoke puts "bullet-time" end end class SeeTheMatrix def invoke puts "woah" end end me = Person.new([]) me.fight # i've got nothing neo = Person.new([KungFu.new, Dodge.new, SeeTheMatrix.new]) neo.fight # "5-fisted punch" # "bullet-time" # "woah" Rails 3 might fight in the matrix like this: class Person def fight end end module KungFu def fight puts "5-fisted punch" super end end module Dodge def fight puts "bullet-time" super end end class Neo < Person include KungFu include Dodge def fight puts "woah" super end end Neo.new.fight # "woah" # "bullet-time" # "5-fisted punch" Maybe a class-based inheritance implementation would be: class Person def fight end end class PersonKnowsKungFu < Person def fight "5-fisted punch" super end end class PersonMovesLikeThem < PersonKnowsKungFu def fight "bullet-time" super end end class Neo < PersonMovesLikeThem def fight "woah" super end end The goal of all of these would be to easily add new skills and characters. Obviously the class-based inheritance example is brittle because it'd take a refactoring to give someone bullet-time without kung-fu. I'm mostly interested in the differences between the "leaf-class-mixins" strategy and the strategy pattern. "Prefer composition over inheritance" would suggest you should use the strategy pattern, but mixing in modules sure seems like a simple and ruby-ish way of achieving the same thing. The only difference I can see is that the strategy pattern allows for run-time skill manipulation, which I don't find myself needing often. What other advantages would I gain from preferring composition here? -- Posted via http://www.ruby-forum.com/.