Skip to content

Instantly share code, notes, and snippets.

@geckofu
Last active August 29, 2015 14:16
Show Gist options
  • Save geckofu/c09f1f21400c2caf3e71 to your computer and use it in GitHub Desktop.
Save geckofu/c09f1f21400c2caf3e71 to your computer and use it in GitHub Desktop.
composite pattern
# use the Composite pattern when you are trying to build a hierarchy
# three moving parts: base class/interface (component), leaf classes, composite classes
class Task
attr_reader :name
def initialize(name)
@name = name
end
def get_time_required
0.0
end
end
class CompositeTask < Task
def initialize(name)
super(name)
@sub_tasks = []
end
def add_sub_task(task)
@sub_tasks << task
end
alias_method :<<, :add_sub_task
def remove_sub_task(task)
@sub_tasks.delete(task)
end
def get_time_required
@sub_tasks.inject(0) do |task, time|
time + task.get_time_required
end
end
end
class AddDryIngredientsTask < Task
def initialize
super("Add dry ingredients")
end
def get_time_required
1.0
end
end
class MakeBatterTask < CompositeTask
def initialize
super('Make batter')
add_sub_task( AddDryIngredientsTask.new )
add_sub_task( AddLiquidTask.new )
add_sub_task( MixTask.new )
end
end
# traverse the tree from leaves to the root:
# add a parent reference
class Task
def initialize(name)
***
@parent = nil
end
end
class CompositeTask < Task
def add_sub_task(task)
@sub_tasks << task
task.parent = self
end
def remove_sub_task(task)
@sub_tasks.delete(task)
task.parent = nil
end
end
# get the ultimate parent
while task
task = task.parent
end
# the usual error of Composite Pattern is that assuming all of the child components
# are leaf objects and not other composites.
# the right way to handle this situation is to define total_num_of_tasks method in the
# component class:
class Task
def total_num_of_tasks
1
end
end
class CompositeTask < Task
def total_num_of_tasks
@sub_tasks.inject(0) do |task, sum|
sum + task.total_num_of_tasks
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment