GOF Series: Episode #4 [The Builder Pattern] - In IronRuby
So first up let me say that the balance of this series of posts on patterns will be presented using either C# or IronRuby as languages to express the GOF patterns. Why IronRuby you ask? I have taken to learning IronRuby and Silverlight as deeply as possible this year and decided to spice things up for myself by incorporating it in this series of posts. Never fear I will continue to demonstrate most of the remaining patterns in C# but will from time to time present the patterns in both languages. For now however it’s the Builder Pattern exclusively in IronRuby for the dynamic language enthusiasts.
IronRuby is a dynamically typed, object oriented language and runs in the Dynamic Language Runtime. We will demonstrate the builder pattern using IronRuby, Windows Forms and the Ruby In Steel plugin for Visual Studio.Net 2008.
The goal of the Builder Pattern is to separate or abstract away the construction of an object and to allow the same / common construction process to create the object regardless of its representation. The different representations of the object being constructed are created by concrete builders, specifically designed to create one and only one representation of the product class.
The players in the story:
-
The Director
- Responsible for constructing the Product object via an interface (mixin in the case of this example using IronRuby) implemented by a concrete builder.
-
The Builder
- Provides the interface (object in this case) that creates the Product(s) constituent parts and is implemented (included as a mixin with IronRuby) by concrete builders.
-
The Concrete Builder
- Builds the constituent parts of the Product object.
-
The Product
- The object whose parts are created by the concrete builder.
In C# or other statically typed languages such as java, the builder pattern relies on an abstract class design and inheritance. In IronRuby there is no concept of an interface therefore a different approach is required. We can use a mixin to provide the common behavioural aspects and use arguments to diverge the different concrete builders. The construction of the ‘Product’ is abstracted from the ‘Director’ by the ‘Builder’ and it’s Concrete implementations. To obtain different representations of the Product object new concrete builder objects are created. The Builder Pattern creates it’s Product object in parts via the Director and Builders abstract signatures, however an alternate approach with IronRuby is to substitute the abstract class for a mixin.
#Product class FootballTeam def team_id?() self.hash end def team_type_name?() @team_type_name end def team_properties?() @team_properties end def initialize(name) @team_type_name = name @team_properties = Hash.new(“Staff Role does not exist!”) end end #Builder module FootballTeamBuilder attr_reader :name attr_writer :name def footy_team?() @footy_team end def build_init() @footy_team = FootballTeam.new(name) end def build_players(number_of_players) @footy_team.team_properties?["Players"] = number_of_players end def build_ball_shape(shape_of_ball) @footy_team.team_properties?["ballshape"] = shape_of_ball end def build_games_per_season(number_of_games) @footy_team.team_properties?["games"] = number_of_games end def print_team_details() attributes = “****************************” + “******************************\r\n” attributes += “Created a #{name} team with the “ + “following attributes :\r\n” @footy_team.team_properties?.each { |k,v| attributes += k.to_s + ” “ + v.to_s + “\r\n” } attributes += “\n***************************” + “*******************************\n” return attributes end end #Concrete Builder” class AustralianRulesFootballTeamBuilder include FootballTeamBuilder def build_all() self.name = “Aussie Rules” build_init() build_ball_shape(“Oval”) build_games_per_season(22) build_players(18) end end #Concrete Builder class RugbyLeagueFootballTeamBuilder include FootballTeamBuilder def build_all() self.name = “Rugby League” build_init() build_ball_shape(“Oval”) build_games_per_season(24) build_players(13) end end #Concrete Builder class SoccerFootballTeamBuilder include FootballTeamBuilder def build_all() self.name = “Soccer” build_init() build_ball_shape(“Round”) build_games_per_season(44) build_players(11) end end #Director Class class GoverningBody def build_football_team(football_team_builder) unless football_team_builder.is_a?(FootballTeamBuilder) fail NoNewMethodError.new(“Cannot build with arguments that are “ + “not FootballTeamBuilder class objects”) end football_team_builder.build_all end end
def Form1_Load(sender, e) #new up a Director f = GoverningBody.new #new up a concrete builder soccer_builder = SoccerFootballTeamBuilder.new #go again a second time with another builder aussie_rules_builder = AustralianRulesFootballTeamBuilder.new #go again a second time with another builder rugby_league_builder = RugbyLeagueFootballTeamBuilder.new #pass the bulders build to the Director f.build_football_team(soccer_builder) f.build_football_team(aussie_rules_builder) f.build_football_team(rugby_league_builder) #store the teams and details in arrays @team1 = [soccer_builder.footy_team?.team_type_name?, soccer_builder.print_team_details] @team2 = [aussie_rules_builder.footy_team?.team_type_name?, aussie_rules_builder.print_team_details] @team3 = [rugby_league_builder.footy_team?.team_type_name?, rugby_league_builder.print_team_details] self.listBox1.Items.Add(@team1[0]) self.listBox1.Items.Add(@team2[0]) self.listBox1.Items.Add(@team3[0]) end
3 Comments so far
Leave a reply









hi Simon,
thanks for giving us some IronRuby love in your patterns series. I’ve been messing around with Ruby for a while, and it’s very nice to see familiar patterns illustrating some dynamic-y goodness.
[Reply]
Dale
I am very excited about the prospects of IronRuby in the .Net environment and certainly feel that learning Ruby is making me a more rounded developer. Hopefully every little bit helps in ‘crossing the chasm’ and I am certainly wishing John Lam and his team every success in getting IronRuby over the line.
[Reply]
[...] incorporate Ruby in the hope of picking up the momentum again, for example I am posting some of my Patterns series in Ruby and even bought Ivan Porto Carrero’s rough cuts of his unfinished book, but still I [...]