CSC/ECE 517 Fall 2009/wiki2 11 zv: Difference between revisions
No edit summary |
|||
Line 51: | Line 51: | ||
def create_something(factory) | def create_something(factory) | ||
new_object = factory.new | new_object = factory.new | ||
puts | puts "created a new #{new_object.class} with a factory" | ||
end | end | ||
Revision as of 18:03, 7 October 2009
Overview
Before starting off with design patterns for Ruby we need to define what a design pattern is, Design patterns can be described as "a general reusable solution to a commonly occurring problem in software design." [1] The idea of design patterns is to not to reinvent the wheel but to solve the current problems by using solutions that have worked in the past. A design pattern names, abstracts, and identifies the key aspects of a common design structure that make it useful for creating a reusable object-oriented design. It helps to identify the classes and instances and the way they collaborate with each other to form a solution to a problem. Design patterns c an be classified into 3 parts Creational, Structural, Behavioral (See if we can give links for these.)
Factory
Factories The factory design pattern is an object oriented design pattern. It is a creational design pattern and deals with the issues faced in creating objects. The main goal of this implementation is to isolate teh code that creates the class form the concete implementation of that class. Ruby example for the same is given below.
Example of Factory Code
class GearFactory def new() if ( ... some condition ) return Sprocket.new() else return Cog().new() end end end
Our client class now becomes:
class GearUser def doSomething(factory ) ... my_gear = factory.new() ... end end
The above code does not have to distinguish between a factory and an ordinary class. We can call the class using the followijng code.
client.doSomething(GearFactory.new) #Use the factory client.doSomething(Cog) #Use the Cog class client.doSomething(Sprocket) #Use the Sprocket class
AbstractFactory Model
Abstract Factory Design Pattern encapsulates a group of objects that have common theme. It implements a generic interface to create these objects that are part of the theme. It does not care about the details of the implementation of these objects. It is a type of Creational pattern [2] “Provide an interface for creating families of related or dependent objects without specifying their concrete classes” [3]
Ruby automatically implements the Abstract Factory pattern as Class Objects. All Class objects have the same interface: the new method of each class object creates new instances of the class. Thus the code can pass references to class objects around and they can be used to call new method without knowing the exact type of object that the class creates.
Class Foo; end Class Bar, end
Here is the use of Abstract Factory Pattern
def create_something(factory)
new_object = factory.new puts "created a new #{new_object.class} with a factory"
end
Here we select a factory to use
Create_something(Foo) Create_something(Bar)
Output of the code:
Created a Foo with a factory
Created a Bar with a factory
The create_something method is creating objects through an abstract interface. It does not have details about implementation used to create these objects. Thus the use of create_something() is used to shield the rest of the code from that knowledge.
But in Java for implementation of Abstract Factory design pattern we need to create a class which has method who defers creation of product objects to its concrete class. This class then needs to be ”extended” by the client class which uses only these interfaces to create objects of concrete class. [4]. Thus Java implementation needs a well defined interface to do so but in Ruby it is directly implemented because of private class object property.
Iterator Design Pattern
An Iterator object encapsulates the internal structure of how the iteration occurs. It is a type of Behavioral design pattern. [5]. “Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.” [6]
Ruby implements iterators with blocks and the ‘each’ method, and with ‘for..in’ statements. For example consider the following example;
def print_element(container) Container.each {|o| puts o.inspect } end
list = [1,2,2,3] hash = {“a”=>1, “b”=>2,”c”=>3, “d”=>4 } print_elements list print_elements hash
The output of the code is,
1 2 3 4 [“a”,1] [“b”,2] [“c”,3] [“d”,4]
In Java implementing Iterator design pattern would again involve having an interface for accessing and traversing the elements which is further implemented by the concrete class. Thus a class who needs to access the list will need to call the interface class. [7] Thus Ruby helps in implementing this design pattern easily by providing functions like “each” which does the handling of the concrete class implementation.