CSC/ECE 517 Fall 2007/wiki1b 3 an: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
Line 32: Line 32:
=== Advantages of Closures ===
=== Advantages of Closures ===


• Designers of software libraries can allow users to customize behavior by passing closures as arguments to important  
• Designers of software libraries can allow users to customize behavior by passing closures as arguments to important functions. For example, a function that sorts values can accept a closure argument that compares the values to be sorted according to a user-defined criterion.
        functions. For example, a function that sorts values can accept a closure argument that compares the values to be sorted  
        according to a user-defined criterion.


• Because closures delay evaluation—i.e., they do not "do" anything until they are called—they can be used to define control  
• Because closures delay evaluation—i.e., they do not "do" anything until they are called—they can be used to define control  
         structures.
         structures.


== Design Pattern ==
== Design Pattern ==

Revision as of 01:30, 11 October 2007

We have said that closures in Ruby can be used to implement the Command and Strategy patterns. Closures are useful in implementing various other design patterns too. Explain which patterns, and give examples, using pseudo-Ruby code (i.e., your code should illustrate how to solve the problem with closures in Ruby, but it doesn't actually have to run, if it would be too complicated to give a running example).


Closures

What are Closures?

Every ruby block is a closure in the sense that it carries around the context in which it was defined. This means that a closure can reference the variables that were in scope when it was defined, even if those variables later go out of scope. This enables us to move around these blocks throughout our code without having to worry about the context. In addition to that, we can also pass a closure to another method which enables us to customize the behavior of the method.

Thus a closure is a block of code that has these three properties

• It can be passed around as a value.

• It can be executed on demand by any procedure or method that has that value.

• It can refer to variables from the context in which it was created (it is “closed” with respect to variable access).

A Simple Closure Example

def remember(&a_block)
 @block = a_block
end
# Invoke the above method, giving it a block that takes a name.
remember {|name| puts "Hello, #{name}!"}
# When the time is right (for the object) -- call the closure!
@block.call("John")
# => "Hello, John!"

Advantages of Closures

• Designers of software libraries can allow users to customize behavior by passing closures as arguments to important functions. For example, a function that sorts values can accept a closure argument that compares the values to be sorted according to a user-defined criterion.

• Because closures delay evaluation—i.e., they do not "do" anything until they are called—they can be used to define control

       structures.

Design Pattern

Closures And Design Patterns

When implementing design patterns, it is often useful to pass around code that needs to be executed later.Using the power of closures,a number of design patterns can be implemented in Ruby in a simpler way as compared to other languages.

Observer Pattern

Description

The observer pattern is used to observe the state of an object in a program. An observer pattern defines a one to many dependency between objects so that when one object changes state all its dependents are notified and updated accordingly

Typical Uses

Observer pattern is mainly used to implement a distributed event handling system where objects are listening for an external event or for changes of the value of an object property.

Examples

1) In a mailing list,where every time an event happens (a new product,a gathering etc) a message is sent to the people subscribed to the list.

2) A change in the data values triggers change in the bar graph pie chart representations in a spreadsheet.

Terminology

In its simplified form, the observer design pattern consists of a subject,and one or more observers,which observe an event in the subject.An event can be a change in the state of the subject and can be defined accordingly.

Subject This class provides an interface for attaching and detaching observers.Contains the following functions

1.Attach – Adds a new observer to the list of observers observing the subject

2.Detach – Deletes an observer from the list of observers observing the subject

3.Notify – Notifies each observer by calling the notify function in the observer,whenever a change occurs.

ConcreteSubject This class provides the state of interest to observers. It also sends a notification to all observers, by calling the Notify function in its super class (i.e, in the Subject class). Contains this function:

GetState - Returns the state of the subject

Observer This class defines an updating interface for all observers, to receive update notification from the subject. The Observer class is used as an abstract class to implement concrete observers. Contains this function:

Notify - An abstract function, to be overridden by concrete observers.

ConcreteObserver This class maintains a reference with the ConcreteSubject, to receive the state of the subject when a notification is received. Contains this function:

Notify - This is the overridden function in the concrete class. When this function is called by the subject, the ConcreteObserver calls the GetState function of the subject to update the information it has about the subject's state.

Structure

Closures and Observer Pattern

Closures can be used to implement Observer pattern.The role of closures can be the basis of the following two applications of Observer design patterns

1.A change in one object requires changing other objects.Also the number of objects to be changed is unknown.

2.The object being changed should be able to notify other objects about the change without having any idea about the current state of the objects.


Pseudocode

class Subject
  def initialize
    @list=[]
  end
  def attach(&list)
    @list << list
  end
  def notify
    @list.each{|x| x.call(@radius)}
  end
  def update(r)
    @radius=r
    notify
  end
end


class Observer1
  def calc_area(radius)
    @area=radius*radius*3.14
    puts "Area #{@area}"
  end
end


class Observer2
 def calc_circumference(radius)
    @circum=2*3.14*radius
    puts "Circumference #{@circum}"
 end
end


o1=Observer1.new
o2=Observer2.new
s=Subject.new
s.attach { |s| o1.calc_area(s)}
s.attach { |s| o2.calc_circumference(s)}
s.update(5)


The output is
Area 78.5
Circumference 31.4


Here we have a subject class that contains the following methods.

1.Attach()

This method is used to update the list of observers

2.Update()

This method updates the radius and calls the notify method.

3.Notify()

This method notifies all the observers in the list about the event which is the change in the value of the radius.

We have two observers for calculating area and circumference. On receiving notify,these functions return updated values of area and circumference depending on the new value of the radius.


Iterator Pattern

Description

The Iterator pattern is a design pattern in which iterators are used to access the elements of an aggregate object sequentially without exposing its underlying representation. An Iterator object encapsulates the internal structure of how the iteration occurs.An aggregate function can be an array or a hash.

Typical Uses

• to access an aggregate object's contents without exposing its internal representation.

• to support multiple traversals of aggregate objects.

• to provide a uniform interface for traversing different aggregate structures

Examples

A tree, linked list, hash table, and an array all need to be iterated with Search, Sort, Next.Using the iterator pattern will reduce the number of redundant procedures written for each aggregate object.


Terminology

• Iterator -defines an interface for accessing and traversing elements.

• ConcreteIterator -implements the Iterator interface and keeps track of the current position in the traversal of the aggregate.

• Aggregate - defines an interface for creating an Iterator object.

• ConcreteAggregate - implements the Iterator creation interface to return an instance of the proper ConcreteIterator.

Structure

Closures and Iterator Pattern

Pseudocode

Following is a simple example which illustrates the iterator pattern using the power of Ruby closures.

   def find_birthdays_in_range(min,max)
   birthdays = [ "1970-06-15", "1975-08-13", "1939-03-21", "2001-12-01" ]
   birthdays.find_all { |birthday| birthday > min && birthday < max }
   end

Here there are 3 functions here that are called from within each other. A : find_birthdays_in_range B : find_all C : anonymous block The third one is the closure ,it accepts one parameter called birthday which is defined in the first function.It iterates over the array(birthdays) and returns only those values in the given range,specified by min and max.


References

1. Programming Ruby:The Pragmatic Programmers Guide

2. Head First Design Patterns

3. Design Patterns - Elements Of Reusable Object Oriented Software

External Links

1. Ruby Standard Library Documentation

2. Features of Ruby

3. Closures in Ruby