CSC/ECE 517 Spring 2014/ch1 1w1l m: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 74: Line 74:


===Strategy Pattern===
===Strategy Pattern===
The Strategy Pattern allows an algorithms behavior to be determined at runtime. It describes the definition of a family of interchangeable algorithm classes whose functionality is different for identically named methods.


<code>
<code>
  class Fighter
  class Report
   def initialize(&fighting_behavior)
  attr_reader :title, :text
    @finish_move = fighting_behavior
  attr_accessor :formatter
   def initialize(&formatter)
  @title = 'Monthly Report'
  @text = [ 'Things are going', 'really, really well.' ]
  @formatter = formatter
   end
   end
  def output_report
  @formatter.call( self )
  end
end
   
   
HTML_FORMATTER = lambda do |context|
   def finish_opponent
  puts('<html>')
    @finish_move.call
   puts(' <head>')
  puts(" <title>#{context.title}</title>")
  puts(' </head>')
  puts(' <body>')
  context.text.each do |line|
  puts(" <p>#{line}</p>" )
   end
   end
  puts(' </body>')
  puts(' </html>')
  end
  end
 
boxer = Fighter.new { puts 'Left hook to the body!' }
boxer.finish_opponent #=> Left hook to the body!
 
mortal_kombat_warrior = Fighter.new { puts 'Blast him with a lighting bolt' }
mortal_kombat_warrior.finish_opponent #=> Blast him with a lighting bolt
 
mma = Fighter.new { puts 'Put you to sleep, Good Night!' }
mma.finish_opponent #=> Put you to sleep, Good Night!
 
lion = Fighter.new { puts 'Bites your head off' }
lion.finish_opponent #=> Bites your head off!
</code>
</code>



Revision as of 02:44, 24 February 2014

Design Patterns Involving Closures

Background

Explanation of Closures

Very simply, a closure is a function that can use a variable that was valid within the scope that the closure was defined, but need not be in-scope where the closure is called. A quick example is very illustrative.

def closure_builder(message="Default"):
    def closure():
        # Message is in-scope here
        print message
    return closure

# Build two functions
default_closure = closure_builder()
custom_closure = closure_builder("Custom")
del closure_builder

# Call the closures you built
default_closure()  # Amazingly, prints "Default"
custom_closure()  # Amazingly, prints "Custom"

Examples

Decorators

Decorators are an interesting and powerful language feature that can be implemented elegantly with closures.

#!/usr/bin/env python

def decorate(func):
    def decorated_func():
        print "About to call func"
        func()
        print "Back from calling func"
    return decorated_func

@decorate
def func_to_decorate():
    print "In func_to_decorate"

func_to_decorate()

[~517/wiki]$ chmod ug+x decorator.py
[~517/wiki]$ ./decorator.py
About to call func
In func_to_decorate
Back from calling func


Command Pattern

The command Pattern can be implemented using proc objects, which are the closure of an object

In the command pattern, commands for objects to be implemented are queued and can be executed at any time. Arguments are considered passed when the method is called.

count = 0

commands = []
(1..10).each do |i|
  commands << proc { count +=i }
end

puts "Count is initially #{count}"
commands.each { |cmd| cmd.call }
puts "Performed all commands. count is #{count}"

Strategy Pattern

The Strategy Pattern allows an algorithms behavior to be determined at runtime. It describes the definition of a family of interchangeable algorithm classes whose functionality is different for identically named methods.

class Fighter
 def initialize(&fighting_behavior)
   @finish_move = fighting_behavior
 end

 def finish_opponent
   @finish_move.call
 end
end
 
boxer = Fighter.new { puts 'Left hook to the body!' }
boxer.finish_opponent #=> Left hook to the body!
 
mortal_kombat_warrior = Fighter.new { puts 'Blast him with a lighting bolt' }
mortal_kombat_warrior.finish_opponent #=> Blast him with a lighting bolt
 
mma = Fighter.new { puts 'Put you to sleep, Good Night!' }
mma.finish_opponent #=> Put you to sleep, Good Night!
 
lion = Fighter.new { puts 'Bites your head off' }
lion.finish_opponent #=> Bites your head off!

See Also

References

<references />