CSC/ECE 517 Fall 2012/ch1b 1w42 js: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
(Added external links for each pattern)
 
(49 intermediate revisions by 2 users not shown)
Line 11: Line 11:
=Overview=
=Overview=


Design Patterns capture solutions that have evolved over time as developers strive for greater flexibility in their software, and they document the solutions in a way which facilitates their reuse in other, possibly unrelated systems.
A design pattern is a general reusable solution to a commonly occurring problem within a given context in software design


The different types of design patterns can be categorized and listed as below:
The different types of design patterns can be categorized and listed as below:


[http://en.wikipedia.org/wiki/Creational_pattern Creational Pattern], which help create the objects for the user, instead of having the user to instantiate the object.
[http://en.wikipedia.org/wiki/Creational_pattern Creational Pattern], which help create the objects for the user, instead of having the user to instantiate the object.
* '''''Factory Pattern''''', which allows a class to defer instantiation to subclasses.  
* [http://www.oodesign.com/factory-pattern.html'''''Factory Pattern'''''], which allows a class to defer instantiation to subclasses.  
* '''''Abstract Factory Pattern''''', which provides an interface for creating related or dependent objects without specifying the objects' concrete classes.
* [http://www.oodesign.com/abstract-factory-pattern.html'''''Abstract Factory Pattern'''''], which provides an interface for creating related or dependent objects without specifying the objects' concrete classes.
* '''''Builder Pattern''''', which separates the construction of a complex object from its representation so that the same construction process can create different representation.  
* [http://www.oodesign.com/builder-pattern.html'''''Builder Pattern'''''], which separates the construction of a complex object from its representation so that the same construction process can create different representation.  
* '''''Prototype Pattern''''', which specifies the kind of object to create using a prototypical instance, and creates new objects by cloning this prototype.  
* [http://www.oodesign.com/prototype-pattern.html'''''Prototype Pattern'''''], which specifies the kind of object to create using a prototypical instance, and creates new objects by cloning this prototype.  
* '''''Singleton Pattern''''', Ensure that only one instance of a class is created and Provide a global access point to the object.  
* [http://www.oodesign.com/singleton-pattern.html'''''Singleton Pattern'''''], which ensures that only one instance of a class is created and provides a global access point to the object.  
[http://en.wikipedia.org/wiki/Structural_pattern Structural Pattern], which employ interfaces to achieve inheritance to enable objects to obtain new functionality.
[http://en.wikipedia.org/wiki/Structural_pattern Structural Pattern], which employ interfaces to achieve inheritance to enable objects to obtain new functionality.
* '''''Adapter Design Pattern''''', which enables classes with incompatible interfaces to work together.
* [http://www.oodesign.com/adapter-pattern.html'''''Adapter Pattern'''''], which 'adapts' one interface for a class into one that a client expects.
* [http://www.oodesign.com/bridge-pattern.html'''''Bridge Pattern'''''], which decouples an abstraction from its implementation so that the two can vary independently.
* [http://www.oodesign.com/composite-pattern.html'''''Composite Pattern'''''], which represents a tree structure of objects where every object has the same interface.
* [http://www.oodesign.com/decorator-pattern.html'''''Decorator Pattern'''''], which adds additional functionality to a class at runtime where subclassing would result in an exponential rise of new classes
* [http://sourcemaking.com/design_patterns/facade'''''Facade Pattern'''''], which creates a simplified interface of an existing interface to ease usage for common tasks.
* [http://www.oodesign.com/flyweight-pattern.html'''''Flyweight Pattern'''''], where a high quantity of objects share a common properties object to save space.
* [http://www.oodesign.com/proxy-pattern.html'''''Proxy Pattern'''''], where a class functions as an interface to another thing.
[http://en.wikipedia.org/wiki/Behavioral_pattern Behavioral Pattern], which are concerned with communication between objects.
[http://en.wikipedia.org/wiki/Behavioral_pattern Behavioral Pattern], which are concerned with communication between objects.
* '''''Command Design Pattern''''', which enables to pass around the code that needs to be executed later.
* [http://www.oodesign.com/command-pattern.html'''''Command Pattern'''''], which enables to pass around the code that needs to be executed later.
* '''''Algorithm Strategy Pattern''''', which helps choose an algorithm to fulfill a task based on some "parameter" of the situation.
* [http://www.oodesign.com/chain-of-responsibility-pattern.html'''''Chain of Responsibility Pattern'''''], where command objects are handled or passed on to other objects by logic-containing processing objects.
* [http://www.oodesign.com/interpreter-pattern.html'''''Interpreter Pattern'''''], which implements a specialized computer language to rapidly solve a specific set of problems.
* [http://www.oodesign.com/iterator-pattern.html'''''Iterator Pattern'''''], where iterators are used to access the elements of an aggregate object sequentially without exposing its underlying representation.
* [http://www.oodesign.com/mediator-pattern.html'''''Mediator Pattern'''''], which provides a unified interface to a set of interfaces in a subsystem.
* [http://www.oodesign.com/memento-pattern.html'''''Memento Pattern'''''], which provides the ability to restore an object to its previous state (rollback).
* [http://www.oodesign.com/observer-pattern.html'''''Observer Pattern'''''], is similar to Publish/Subscribe or Event Listener. Objects register to observe an event that may be raised by another object.
* [http://sourcemaking.com/design_patterns/state'''''State Pattern'''''], is a clean way for an object to partially change its type at runtime.
* [http://www.oodesign.com/strategy-pattern.html'''''Strategy Pattern'''''], where Algorithms can be selected on the fly.
* [http://www.oodesign.com/template-method-pattern.html'''''Template Pattern'''''], which describes the program skeleton of a program.
* [http://www.oodesign.com/visitor-pattern.html'''''Visitor Pattern'''''], is a way to separate an algorithm from an object.


'''''There are lot of patterns in each of the categories. There's no mention of them. If the idea is that we these are the patterns available out of the box in ruby, it should be explicitly mentioned here.'''''
Some of the Patterns that are more commonly used with Ruby are explained below.
 
=Creational Patterns=
Creational Patterns and Design Patterns that somehow control the mechanism by which objects are created. They generally help to provide the following capabilities <ref>Stelting, S. (2002). Creational patterns. In Applied java patterns (p. 5). Palo Alto, California: Sun Microsystems. Retrieved from www.pearsonhighered.com/samplechapter/0130935387.pdf</ref>:
* Generic instantiation – This allows objects to be created in a system without having to identify a specific class type in code.
* Simplicity – Some of the patterns make object creation easier, so callers will not have to write large, complex code to instantiate an object.
* Creation constraints – Some patterns enforce constraints on the type or number of objects that can be created within a system. The Singleton Pattern is an example of this type.


=Creational Pattern=
==Singleton Pattern==
==Singleton Pattern==
The first design pattern one should know about is the [http://www.oodesign.com/singleton-pattern.html Singleton patterns]. It is basically the case, where the Class can instantiate only one object, which is globally available.
'''''Need better definition.'''''


Below is an illustration of the general Syntax of Singleton Design Pattern in Ruby:
The [http://www.oodesign.com/singleton-pattern.html Singleton pattern] is one of the simplest design patterns: it involves only one class which is responsible to instantiate itself, to make sure it creates not more than one instance; in the same time it provides a global point of access to that instance.For example, in a system there should be only one window manager (or only a file system or only a print spooler). Usually singletons are used for centralized management of internal or external resources and they provide a global point of access to themselves.
Illustrated below is the syntax of using singleton in Ruby:


  require 'singleton'
  require 'singleton'
  class Example
  class Registry
    include Singleton
  include Singleton
    ...
  attr_accessor :val
  end
  end
It could be noticed that one must 'require' a module called 'singleton' and include the module within the class.
This adds the singleton flavour to your class. Now to test if it can create multiple instances, we can inquisitively try this,
  raisesError = Example.new
  ruby-1.9.2-p290 :026 > raisesError = Example.new
  NoMethodError: private method `new' called for Example:Class
We will soon find out we are greeted with the NoMethodError( Some kind of an error is expected ). So how do we use a singleton pattern? We create an instance of it using the keyword 'instance'
''''''What is meant by Some kind of error is expected? Content here is good, will need to rephrase.''''''
a = Example.instance
=> #<Example:0x9361cb8>
b = Example.instance
=> #<Example:0x9361cb8>


The above illustrates how to create the instance of the Singleton class. It also illustrates another point. Even though two 'instances' have supposedly been created, both of them happen to contain reference to the same object.
The Singleton pattern is available as a '''mixin''' in the Ruby library. Including it in the code makes the new method private and provides an instance method used to create or access the single instance.
This further proves that only one object can be created for a Singleton.<BR>


'''''Rephrase again. Not formal enough'''''
r = Registry.new #throws a NoMethodError as the "new" method is private
r = Registry.instance
r.val = 5
s = Registry.instance # a new reference to the existing object is created.
puts s.val >> 5
s.val = 6
puts r.val >> 6
s.dup >> TypeError: can’t duplicate instance of singleton Registry


That was the Ruby's default way to create singletons. Singletons can be created manually without using the 'singleton' module.
Singletons can also be created without using the 'singleton' module.


  class Single_ton
  class Single_ton
  def initialize
  def initialize
     puts "Initialised"
     puts "Initialized"
  end
  end
   
   
Line 84: Line 92:
  end
  end
   
   
The above snippet is actually a singleton class. A cursory reading shall read the logic behind singleton-ing the class. An object to the same class has been created as a class variable. a "instance" method is defined. The "new" method is made 'private'. This makes sure that objects of the Single_ton cannot be created.


The above snippet is actually a singleton class. A cursory reading shall read the logic behind singleton-ing the class. An object to the same class has been created as a class variable. a ".instance" method is defined. One more thing to notice is that, "new" method is made 'private'. This makes sure that one cannot create anymore objects of the singleton.
puts Single_ton.instance  >>  <Single_ton:0x94483d4>
Single_ton.instance.print_something >> This prints something


Single_ton.instance
The above snippet shows that the class 'behaves' like a singleton.
=> #<Single_ton:0x94483d4>
Single_ton.instance.print_something
This prints something


The above snippet shows that our class 'behaves' like a singleton. We have a '.instance' method defined and it works.
The class diagram<ref>Singleton pattern - implementation. In Oodesign. Retrieved from http://www.oodesign.com/singleton-pattern.html</ref> for Singleton pattern is illustrated below:
The method could be accessed by accessing the lone object inside the class.


The Singleton Pattern is useful in situations where serialization is desirable, example logging, communication and database access etc. In these cases, only a single instance of the class is created which accesses and modifies the methods of the class. This ensures safety and also make the single instance responsible for the class.<br>
[[File:Singleton implementation - uml class diagram.gif]]
[http://c2.com/cgi/wiki?SingletonPattern Here ] is more to read on Singleton patterns.


'''''Feel like there's some flab in the Singleton section that we can cut. Also could think of adding subsections for Default Implemenation, Custom Implementation, Uses etc.'''''
The Singleton Pattern defines a getInstance() operation which exposes the unique instance which is accessed by the clients. The getInstance() is is responsible for creating its class unique instance in case it is not created yet and to return that instance.
For more details, follow this [http://www.oodesign.com/singleton-pattern.html link]


=Structural Patterns=
=Structural Patterns=
Structural Patterns are Design Patterns which describe how Classes and Methods can be combined to form larger, more complex structures. They involve connection between objects.
In some sense, structural patterns are similar to the simpler concept of data structures <ref>(n.d.). What is a structural pattern? Retrieved from Gof Patterns - Gang of Four Patterns website: http://www.gofpatterns.com/design-patterns/module5/structural-design-pattern.php</ref>.
However, structural design patterns also specify the methods that connect objects, not merely the references between them. Furthermore, data structures are fairly static entities. They only describe how data is arranged in the structure. A structural design pattern also describes how data moves through the pattern.
==Adapter Pattern==
==Adapter Pattern==


An [http://www.oodesign.com/adapter-pattern.html Adapter pattern], also known as the Wrapper Pattern enables classes with incompatible interfaces to work together, by providing the users with its interface. This is achieved by:
An [http://www.oodesign.com/adapter-pattern.html Adapter pattern], also known as the Wrapper Pattern, enables classes with incompatible interfaces to work together, by providing the users with a compatible interface.
<br>
<br>
In other words, when we want our new class to support a pre-existing feature, instead of modifying our new class, we can 'wrap' a similar feature in our new class to behave like the older class so that the pre-existing feature is supported.
In other words, when we want our new class to support a pre-existing feature, instead of modifying our new class, we can 'wrap' a similar feature in our new class to behave like the older class so that the pre-existing feature is supported.
<br>
<br>


'''''Some cleaning up to do'''''
Lets look at a simple example.<ref>Olsen, R. (2007). Filling in the gaps with the adapter. In Design patterns in ruby (pp. 164-165). Addison Wesley.</ref>


Consider a software company located in United Kingdom. Lets assume they have these classes in their system.
Consider a class ''Encrypter'' which is used to encrypt files. The ''encrypt'' method takes two open files as arguments. One is a reader which is the input file and other is the writer which is the output file where the encrypted data is stored. It uses a simple encryption algorithm to encrypt each character with a user-specified key.


  class Bicycle
  class Encrypter
   def rideBiCycle
   def initialize(key)
     puts 'Iam riding a bicycle'
     @key = key
    end
   end
   end
   
   
The following class has a method which calls the method 'rideBiCycle' in the passed argument.  
  def encrypt(reader, writer)
    key_index = 0
class Tester
    while not reader.eof?
  def displayRide(object)
      clear_char = reader.getc
    object.rideBiCycle
      encrypted_char = clear_char ^ @key[key_index]
     end
      writer.putc(encrypted_char)
      key_index = (key_index + 1) % @key.size
     end  
   end
   end
end


Now, If an American company buys this British company and tries to reuse the code. It has the following class already to its use.
Now suppose a string is to be encrypted instead of a file. To be able to use the same ''Encrypter'' class an object is required that looks like an open file - exposes the same methods as the Ruby IO object - on the outside, but actually fetches the data from a string on the inside.


class Bike
So, lets define a ''StringIOAdapter'' class:
  def rideBike
    puts 'I am riding a bike'
    end
  end


But, the problem is that, Bike doesn't have the function 'rideBiCycle', so it cannot use the Tester class directly. If that tester class sits in a very important part of the code, there is a problem. Now the way out is to create a 'adapter' which assimilates a 'bike' object. This adapter is actually a 'Bike' which can mimic itself like a 'Bicycle' by supporting the method 'rideBiCycle'.
class StringIOAdapter
<br>
  def initialize(string)
Now to understand it. We will create a bunch of instances.
    @string = string
    @position = 0
  end
  def getc
    if @position >= @string.length
      raise EOFError
    end
    ch = @string[@position]
    @position += 1
    return ch
  end
  def eof?
    return @position >= @string.length
  end
end


cycle = Bicycle.new
The ''StringIOAdapter'' has two instance variables: a reference to the string to be encrypted and a position index. Each time the function getc is called, the ''StringIOAdapter'' will return the character at current position and increment the position index. If no more characters are left in the string an ''EOFError'' will be raised. The function ''eof?'' will return ''true'' if the string has run out of characters but otherwise will return ''false''.
cycle.rideBiCycle
Iam riding a bicycle


test = Tester.new
To use ''Encrypter'' with ''StringIOAdapter'', the ''reader'' input object is defined to be of type ''StringIOAdapter''.
test.displayRide(cycle)


  bike = Bike.new
  encrypter = Encrypter.new('OOLS')
  bike.rideBike
  reader= StringIOAdapter.new('TA position open with Prof. XYZ')
  I am riding a bike
  writer=File.open('out.txt', 'w')
encrypter.encrypt(reader, writer)


So far, the respective objects are working well when used in isolation. But when we have to do this,
Thus the Adapter bridges the chasm between the interface you have and the interface you need.


  test.displayRide(bike)
The class diagram of Adapter class is usually given as:
  NoMethodError: undefined method `rideBiCycle' for #<Bike:0x94b4494>


We encounter an error which is pretty obvious because rideBiCycle is not defined in Bike. Now let us define the adapter,
[[File:Class Diagram - Adapter.png]]
class BikeAdapter
  def initialize(bike)
    @bikeObject = bike
    end
  def rideBiCycle
    @bikeObject.rideBike
  end                                                                                                               
end


Now we can try the failed method call like this,
The client expects the target to have some interface. But the target is actually an implementation of the Adapter. The Adapter defines a compatible interface while at the same time there is a reference to a second object - the Adaptee - buried inside it. The Adaptee actually performs the work.
 
adapter = BikeAdapter.new(bike)
test.displayRide(adapter)
Iam riding a bike
 
Voila! We have succesfully 'adapted' Bike class to behave like 'Bicycle'.<br>
[http://c2.com/cgi/wiki?AdapterPattern This one ] is a good read on Adapter patterns and also contains links to other articles about Adapter Pattern.
 
'''''I found the example thoroughly confusing. Let me know what you think.'''''


=Behavioral Patterns=
=Behavioral Patterns=
==Closures and Patterns==
As state earlier, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.<ref>(n.d.). Behavioral patterns. Retrieved from SourceMaking website: http://sourcemaking.com/behavioral_patterns</ref>
==Command Pattern==


Patterns can be implemented using Closures. A [http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2011/ch3_3a_av#Closures Closure] can be described as a block of code ith the properties mentioned below:
The design patterns we saw above deal with classes and work around the way classes and objects are manipulated, interpreted, created etc. Actually, the adapter pattern bases its necessity on the need for 'code reuse'. But, it can only implement code reuse at a class or method level. But sometimes code must be reused at an even finer level. For example, Sometimes one might need to store bunch of code to be used by a peer or at a later stage. This bunch of code is not associated with any class, or any method.


* The block of code can be passed around like a value.
[http://www.oodesign.com/command-pattern.html Command Pattern] is useful in such cases. With command pattern it is possible to store a piece of code or a set of commands to be executed at a later stage.
* Any procedure or method that has the value can execute it.
* A Closure can refer to the variables from the context in which it was created.  


'''''Why does he/she start off with Closures and Patterns? Since there's a whole section on it elsewhere, makes no sense to give such a hasty explanation that doesn't make stuff clear at all. What is meant by Patterns can be implemented using closures? Can all patterns be implemented using closures?'''''
Lets consider a simple example of a GUI button that can be configured to do a variety of actions.<ref>Olsen, R. (2007). Getting things done with commands. In Design patterns in ruby (pp. 147-148). Addison Wesley.</ref> These actions could be saving data to database, making a network connection, navigating to another page, etc.


The Command Design Pattern and Strategy Design Patterns are examples of this.
class UserButton
  attr_accessor :command
  def initialize()
   
  end
  #
  # Button rendering and management code
  #
  def on_button_push
    #
    # Do some action
    #
  end
end


==Command Pattern==
Without the use of the Command Pattern, we could implement a solution here by inheriting the ''UserButton'' into subclasses like ''DatabaseButton'', ''NetworkButton'', etc. For example:


The design patterns we saw above deal with classes and work around the way classes and objects are manipulated, interpreted, created etc. Actually, the adapter pattern bases its necessity on the need for 'code reuse'. But, it can only implement code reuse at a class or method level. What if we need a more finer to do it.For example, Sometimes one might need to store bunch of code to be used by a peer or himself at a later point. This bunch of code is not associated with any class, or any method.
class DatabaseButton
<br>
  attr_accessor :command
  def initialize()
  end
  #
  # Button rendering and management code
  #
  def on_button_push
    #
    # Database operations like InsertIntoDatabase(column, value)
    #
  end
end


[http://www.oodesign.com/command-pattern.html Command Patterns] lends itself to our use at this point. With command pattern it is possible to store a piece of code or a set of commands to be executed at a later stage. And of course, this is implemented with the use of procs in Ruby.
This is however a tedious and rigid solution. If suppose on certain button clicks you only wanted to update the database value and not insert. You would either have to create a new subclass with this functionality or check for which operation is required in the on_button_push method and execute separate queries.


<br>
The Command Pattern provides an easier way to implement this. The simplest way to implement the Command Pattern in Ruby is through the use of [http://www.ruby-doc.org/core-1.9.2/Proc.html Proc Object] with [http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2012/ch1_1w32_cm Closures] and [http://www.elonflegenheimer.com/2012/07/08/understanding-ruby-closures.html Blocks].  
This is how command pattern is usually implemented. We have a class which holds the commands as a [http://www.ruby-doc.org/core-1.9.2/Proc.html Proc Object]. And whenever it is to be called, 'call' is used to execute that proc.


class Command
Consider the following definition for the ''UserButton'' class.
  def initialize(input)
    @local_proc = input
  end


   def return_proc
class UserButton
    @local_proc
  attr_accessor :command
   def initialize(&block)
    @command = block
   end
   end
  #
  # Button rendering and management code
  #
  def on_button_push
    @command.call if @command
  end
  end
  end


Now we have a class that stores a command. Now let us create a 'command'.  
Here the ''@command'' instance variable is a Proc object. In simple terms, it is a chunk of code that can be executed with the ''call'' method.


myProc = proc{ puts 8 }
To instantiate a ''UserButton'' for database insertion, a code block is passed when the object is created.


Now we have a proc object that we want to use.
new_button = UserButton.new do
  #
  # Database operations like InsertIntoDatabase(column, value)
  # or
  # Network link creation
  # or
  # Navigate to another page
  #
end


obj = Command.new(myProc)
The class diagram for the Command Pattern is fairly simple. It consists of a number of classes which share the same interface.
obj.return_proc.call
[[File:Class Diagram - Command Pattern.png]]
8


Then we create an object storing myProc inside it. Then we use the object to return the proc and use 'call' on it to execute it. One could also create an array of commands by simply creating an array of Command objects and storing the proc in them. <br>


One important use of the Command Pattern is to enable the client undo what he has already done, or redo what has been undone by the user. This is done by maintaining a history of the commands executed. As and when the user makes changes, the system creates command after command, executing each command immediately to effect the change. Every undo - able command holds two methods - the execute and the unexecute method.
An interesting usage of the command pattern is to implement the Undo functionality.<ref>Olsen, R. (2007). Getting things done with commands. In Design patterns in ruby (pp. 151-153). Addison Wesley. </ref> This requires definition of a unexecute method which undoes the actions done in the execute method. A code example can be found [http://www.java2s.com/Code/Ruby/Design-Patterns/UndobyaCommand.htm here.].
The commands are stored in a list and when the user decides to undo a change, the last command on the list is executed to undo the change. The changes can be undone, by going back the history of commands. The redo is done in the similar way where the the commands are re-executed beginning from the last change that what undone to reapply the changes undone. A simple example of the undo - redo use of a Command Pattern is a Calculator with many undo - redo options.


'''''This is not much use without a code example'''''
==Strategy Pattern==
 
==Algorithm Strategy Pattern==


The [http://www.oodesign.com/strategy-pattern.html Strategy Pattern] helps choose an algorithm to accomplish a task based on some "parameters" of the situation. Also known as the Policy Pattern, it enables selection of algorithms at runtime. This pattern allows the algorithm to vary irresepctive of the user that uses it.
The [http://www.oodesign.com/strategy-pattern.html Strategy Pattern] helps choose an algorithm to accomplish a task based on some "parameters" of the situation. Also known as the Policy Pattern, it enables selection of algorithms at runtime. This pattern allows the algorithm to vary irresepctive of the user that uses it.
Line 232: Line 270:
The strategy pattern ''"defines a family of algorithms, encapsulates each one, and makes them interchangeable"''.
The strategy pattern ''"defines a family of algorithms, encapsulates each one, and makes them interchangeable"''.


Consider as an example, a class that that converts among different types of file formats like jpeg, jif, png etc. We can write a case statement to choose what algorithm has to be employed for each type of format. Another example could be performing validation on incoming data. Here we can select a validation algorithm based on the type and source of data.   
Consider as an example, a class that that converts among different types of file formats like jpeg, gif, png etc. A case statement can be used to choose what algorithm has to be employed for each type of format. Another example could be performing validation on incoming data, where selection of a validation algorithm is based on the type and source of data.   


A Strategy Pattern is best implemented using [http://www.ruby-doc.org/core-1.9.2/Proc.html Proc Objects]. Below is an example of the Strategy Pattern which deals with areas of geometric shapes:
A Strategy Pattern is best implemented using [http://www.ruby-doc.org/core-1.9.2/Proc.html Proc Objects]. An example<ref name = 'multiple'>Olsen, R. (2007). Chapter: 4. replacing the algorithm with the strategy. In Design patterns in ruby (pp. 78-109). Addison Wesley. </ref> of the Strategy Pattern which deals with formatting styles of the report:


  class findArea
  class Report
     attr_accessor :strategy
    attr_reader :title, :text
     def calArea(x,y)
     attr_accessor :formatter
           strategy.call(*args)
     def initialize(formatter)
           #Initialize title and text
          @formatter = formatter
     end
     end
    def area_square … end
    end
    def area_rect … end
class Formatter
  def output_report( title, text )
  raise 'Abstract method called'
  end
  end
  end
   
   
Here, we have a class findArea, which calculates the area of the given geometric shape by invoking the methods area_square or area_rect based upon whether the given figure is a square or rectangle.
class HTMLFormatter < Formatter
  def output_report( title, text )
  puts('<html>')
  #More HTML formatting code
  puts('</html>')
  end
end
class PlainTextFormatter < Formatter
  def output_report(title, text)
    #More Plain Test formatting code
    puts(line)
  end
end
 
The above snippet depicts the structure of the Report class, Formatter class(super class), HtmlFormatter class and PlainTextFormatter class(subclasses of Formatter class). The Report class' initialize method invokes the particular formatter class depending upon the formatter specified. These formatter invocations are not specified in advance, hence the Report class has to choose the required formatter function at the run time.  


sides = findArea.new
  if(type == :HTML)
  if x == y
report = Report.new(HTMLFormatter.new) #HTML Formatter
      puts "The given object is a square"
      sides.strategy = findArea.method(:area_square)
  else
  else
      puts "The given object is a rectangle"
report = Report.new(PlainTextFormatter.new) #formatter type changed to Plain Text Formatter
      sides.strategy = findArea.method(:area_rect)
 
  end
  report.output_report # HTML/Plaintext (depends on type variable) Formatter method
  sides.calArea(x,y)
   
 
The Strategy pattern is based on composition and delegation, rather than on inheritance, hence it is easy to switch strategies at runtime.
Thus the path or strategy chosen is based on the formatter invocation on runtime.Therefore, the algorithm that will be selected for displaying the text, is decided at run time.
 
Illustrated below is the class diagram of Strategy Pattern Design:
 
[[File:Strategy_class_diagram.jpg]]


Here, the path or strategy chosen is based on an if condition involving the values of x and y which are not known until runtime. Therefore, the algorithm that will be made use of to calculate the area, is decided at run time. The strategy that will be chosen depends on many factors which change dynamically.
The GoF call this “pull the algorithm out into a separate object” technique the Strategy pattern (above Figure). The context class is the class that uses Strategy encapsulation. The Strategy1 and Strategy2 are strategies that get actually chosen by context class.
The key idea underlying the Strategy pattern is to define a family of objects, the strategies, which all do the same thing— in given example, format the report. Not only does each strategy object perform the same job, but all of the objects support exactly the same interface. In given example, both of the strategy objects support the output_report method.
For more on Strategy Pattern, read the reference book<ref name = 'multiple'>Olsen, R. (2007). Chapter: 4. replacing the algorithm with the strategy. In Design patterns in ruby (pp. 78-109). Addison Wesley. </ref>.


=Differences between Command and Strategy Pattern=
==Differences between Command and Strategy Pattern==


* A Command Pattern encapsulates a single action. A command object has a single method with a generic signature associated with it.  
* A Command Pattern encapsulates a single action. A command object has a single method with a generic signature associated with it.  
* A Strategy Pattern, enables us to customize an algorithm, deciding which algorithm has to be made use of depending on a number of dynamically changing factors. A given strategy has many methods associated with it.
* A Strategy Pattern, enables us to customize an algorithm, deciding which algorithm has to be made use of depending on a number of dynamically changing factors. A given strategy has many methods associated with it.


=Comparsion of the different Design Patterns=
=Comparison of the different Design Patterns=


{| class="wikitable sortable" style="font-size: 90%; text-align: center; width: auto;"
{| class="wikitable sortable" style="font-size: 90%; text-align: center; width: auto;"
Line 277: Line 343:
! Ensure only one object of a class is instantiated, provide a global point of access to that object
! Ensure only one object of a class is instantiated, provide a global point of access to that object
! Convert the interface of a class into one that the client expects  
! Convert the interface of a class into one that the client expects  
! Encapsulate a request in an object and allow the parameterization of clients with different requests
! Encapsulate a request in an object and allow the parametrization of clients with different requests
! Encapsulate a set of algorithms and use them interchangeably.
! Encapsulate a set of algorithms and use them interchangeably.
|-  
|-  
Line 293: Line 359:
|}
|}


'''''We could also add a section on drawbacks of design patterns. I found a link on that.'''''
=See Also=
=See Also=


[http://www.oodesign.com 1. Object Oriented Design]
* [http://www.oodesign.com Object Oriented Design]


[http://en.wikipedia.org/wiki/Object-oriented_programming 2. Object - Oriented Programming]
* [http://en.wikipedia.org/wiki/Object-oriented_programming Object - Oriented Programming]


[http://c2c.com 3. More Object oriented Programming]
* [http://c2c.com More Object oriented Programming]


==References==
* [http://designpatternsinruby.com/section01/article.html Article on Design Patterns in Ruby]


[http://designpatternsinruby.com/section01/article.html 1. Article on Design Patterns in Ruby]
* [http://www.uml.org.cn/c++/pdf/DesignPatterns.pdf Design Patterns - Elements of Reusable Object Oriented Software by Erich Gamma]  


[http://www.uml.org.cn/c++/pdf/DesignPatterns.pdf 2. Design Patterns - Elements of Reusable Object Oriented Software by Erich Gamma]  
* [http://en.wikipedia.org/wiki/Singleton_pattern Wiki - Singleton Pattern]


[http://en.wikipedia.org/wiki/Singleton_pattern 3. Wiki - Singleton Pattern]
* [http://en.wikipedia.org/wiki/Adapter_pattern Wiki - Adapter Pattern]


[http://en.wikipedia.org/wiki/Adapter_pattern 4. Wiki - Adapter Pattern]
* [http://en.wikipedia.org/wiki/Command_pattern Wiki - Command Pattern]


[http://en.wikipedia.org/wiki/Command_pattern 5. Wiki - Command Pattern]
* [http://en.wikipedia.org/wiki/Strategy_pattern Wiki - Strategy Pattern]


[http://en.wikipedia.org/wiki/Strategy_pattern 6. Wiki - Strategy Pattern]
* [http://en.wikipedia.org/wiki/Closure_(computer_science) Wiki - Closures]


[http://en.wikipedia.org/wiki/Closure_(computer_science) 7. Wiki - Closures]
* [http://courses.ncsu.edu/csc517//common/lectures/notes/lec13.pdf Lec 13 - Class Notes]


[http://courses.ncsu.edu/csc517//common/lectures/notes/lec13.pdf 8. Lec 13 - Class Notes]
* [http://www.cs.toronto.edu/~arnold/407/06s/lectures/studentPresentations/stateStrategy/state_strat_pres.ppt State and Strategy Pattern]


[https://docs.google.com/a/ncsu.edu/viewer?a=v&q=cache:UGImuHnhO8MJ:www.cs.toronto.edu/~arnold/407/06s/lectures/studentPresentations/stateStrategy/state_strat_pres.ppt+disadvantages+of+strategy+pattern&hl=en&gl=us&pid=bl&srcid=ADGEEShbX8h_8wQ7PkIoXMKwXjPgISI7dduhY-HrO8fUV8lntQw0RYYWQ-eG_hLAxTT3pjUj5j5Dj8F7-baC3D-C6Znv_YTujBdB_E6-WkZ9KMe2jWXGtZgeRtMcwEJtpqN8JNOC9itc&sig=AHIEtbSP_rpR12IcGL1KyQAhi0PGeUQqrQ&pli=1 9. Command and Strategy Pattern]
* [http://www.codeproject.com/KB/architecture/commandpatterndemo.aspx Command Pattern]


[http://www.codeproject.com/KB/architecture/commandpatterndemo.aspx 9. Command Pattern]
=References=
<references />
The old wiki can be found at http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2011/ch4_4h_sv

Latest revision as of 15:30, 10 October 2012

Design Patterns in Ruby

"Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice" - Christopher Alexander

"In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design".

A Design Pattern is a template to solve a problem which can be used in many different situations. It names, abstracts and identifies the key aspects of a common design structure that makes it useful for creating a reusable object - oriented design. Design Patterns in Object - Oriented Languages help show the relationship between the different classes and objects in the program. Design Patterns are tools for building software.

Overview

A design pattern is a general reusable solution to a commonly occurring problem within a given context in software design

The different types of design patterns can be categorized and listed as below:

Creational Pattern, which help create the objects for the user, instead of having the user to instantiate the object.

  • Factory Pattern, which allows a class to defer instantiation to subclasses.
  • Abstract Factory Pattern, which provides an interface for creating related or dependent objects without specifying the objects' concrete classes.
  • Builder Pattern, which separates the construction of a complex object from its representation so that the same construction process can create different representation.
  • Prototype Pattern, which specifies the kind of object to create using a prototypical instance, and creates new objects by cloning this prototype.
  • Singleton Pattern, which ensures that only one instance of a class is created and provides a global access point to the object.

Structural Pattern, which employ interfaces to achieve inheritance to enable objects to obtain new functionality.

  • Adapter Pattern, which 'adapts' one interface for a class into one that a client expects.
  • Bridge Pattern, which decouples an abstraction from its implementation so that the two can vary independently.
  • Composite Pattern, which represents a tree structure of objects where every object has the same interface.
  • Decorator Pattern, which adds additional functionality to a class at runtime where subclassing would result in an exponential rise of new classes
  • Facade Pattern, which creates a simplified interface of an existing interface to ease usage for common tasks.
  • Flyweight Pattern, where a high quantity of objects share a common properties object to save space.
  • Proxy Pattern, where a class functions as an interface to another thing.

Behavioral Pattern, which are concerned with communication between objects.

  • Command Pattern, which enables to pass around the code that needs to be executed later.
  • Chain of Responsibility Pattern, where command objects are handled or passed on to other objects by logic-containing processing objects.
  • Interpreter Pattern, which implements a specialized computer language to rapidly solve a specific set of problems.
  • Iterator Pattern, where iterators are used to access the elements of an aggregate object sequentially without exposing its underlying representation.
  • Mediator Pattern, which provides a unified interface to a set of interfaces in a subsystem.
  • Memento Pattern, which provides the ability to restore an object to its previous state (rollback).
  • Observer Pattern, is similar to Publish/Subscribe or Event Listener. Objects register to observe an event that may be raised by another object.
  • State Pattern, is a clean way for an object to partially change its type at runtime.
  • Strategy Pattern, where Algorithms can be selected on the fly.
  • Template Pattern, which describes the program skeleton of a program.
  • Visitor Pattern, is a way to separate an algorithm from an object.

Some of the Patterns that are more commonly used with Ruby are explained below.

Creational Patterns

Creational Patterns and Design Patterns that somehow control the mechanism by which objects are created. They generally help to provide the following capabilities <ref>Stelting, S. (2002). Creational patterns. In Applied java patterns (p. 5). Palo Alto, California: Sun Microsystems. Retrieved from www.pearsonhighered.com/samplechapter/0130935387.pdf</ref>:

  • Generic instantiation – This allows objects to be created in a system without having to identify a specific class type in code.
  • Simplicity – Some of the patterns make object creation easier, so callers will not have to write large, complex code to instantiate an object.
  • Creation constraints – Some patterns enforce constraints on the type or number of objects that can be created within a system. The Singleton Pattern is an example of this type.

Singleton Pattern

The Singleton pattern is one of the simplest design patterns: it involves only one class which is responsible to instantiate itself, to make sure it creates not more than one instance; in the same time it provides a global point of access to that instance.For example, in a system there should be only one window manager (or only a file system or only a print spooler). Usually singletons are used for centralized management of internal or external resources and they provide a global point of access to themselves. Illustrated below is the syntax of using singleton in Ruby:

require 'singleton'
class Registry
  include Singleton
  attr_accessor :val
end

The Singleton pattern is available as a mixin in the Ruby library. Including it in the code makes the new method private and provides an instance method used to create or access the single instance.

r = Registry.new #throws a NoMethodError as the "new" method is private
r = Registry.instance
r.val = 5
s = Registry.instance # a new reference to the existing object is created. 
puts s.val >> 5
s.val = 6
puts r.val >> 6
s.dup >> TypeError: can’t duplicate instance of singleton Registry

Singletons can also be created without using the 'singleton' module.

class Single_ton
def initialize
   puts "Initialized"
end

@@instance = Single_ton.new
 
def self.instance
   return @@instance
end
 
def print_something
  puts "This prints something"
end
  
private_class_method :new
end

The above snippet is actually a singleton class. A cursory reading shall read the logic behind singleton-ing the class. An object to the same class has been created as a class variable. a "instance" method is defined. The "new" method is made 'private'. This makes sure that objects of the Single_ton cannot be created.

puts Single_ton.instance  >>  <Single_ton:0x94483d4> 
Single_ton.instance.print_something >> This prints something

The above snippet shows that the class 'behaves' like a singleton.

The class diagram<ref>Singleton pattern - implementation. In Oodesign. Retrieved from http://www.oodesign.com/singleton-pattern.html</ref> for Singleton pattern is illustrated below:

The Singleton Pattern defines a getInstance() operation which exposes the unique instance which is accessed by the clients. The getInstance() is is responsible for creating its class unique instance in case it is not created yet and to return that instance. For more details, follow this link

Structural Patterns

Structural Patterns are Design Patterns which describe how Classes and Methods can be combined to form larger, more complex structures. They involve connection between objects.

In some sense, structural patterns are similar to the simpler concept of data structures <ref>(n.d.). What is a structural pattern? Retrieved from Gof Patterns - Gang of Four Patterns website: http://www.gofpatterns.com/design-patterns/module5/structural-design-pattern.php</ref>.

However, structural design patterns also specify the methods that connect objects, not merely the references between them. Furthermore, data structures are fairly static entities. They only describe how data is arranged in the structure. A structural design pattern also describes how data moves through the pattern.

Adapter Pattern

An Adapter pattern, also known as the Wrapper Pattern, enables classes with incompatible interfaces to work together, by providing the users with a compatible interface.
In other words, when we want our new class to support a pre-existing feature, instead of modifying our new class, we can 'wrap' a similar feature in our new class to behave like the older class so that the pre-existing feature is supported.

Lets look at a simple example.<ref>Olsen, R. (2007). Filling in the gaps with the adapter. In Design patterns in ruby (pp. 164-165). Addison Wesley.</ref>

Consider a class Encrypter which is used to encrypt files. The encrypt method takes two open files as arguments. One is a reader which is the input file and other is the writer which is the output file where the encrypted data is stored. It uses a simple encryption algorithm to encrypt each character with a user-specified key.

class Encrypter
  def initialize(key)
    @key = key 
  end

  def encrypt(reader, writer)
    key_index = 0
    while not reader.eof?
      clear_char = reader.getc
      encrypted_char = clear_char ^ @key[key_index]
      writer.putc(encrypted_char)
      key_index = (key_index + 1) % @key.size
    end 
  end
end

Now suppose a string is to be encrypted instead of a file. To be able to use the same Encrypter class an object is required that looks like an open file - exposes the same methods as the Ruby IO object - on the outside, but actually fetches the data from a string on the inside.

So, lets define a StringIOAdapter class:

class StringIOAdapter
  def initialize(string)
    @string = string
    @position = 0
  end

  def getc
    if @position >= @string.length
      raise EOFError
    end
    ch = @string[@position]
    @position += 1
    return ch
  end

  def eof?
    return @position >= @string.length
  end 
end

The StringIOAdapter has two instance variables: a reference to the string to be encrypted and a position index. Each time the function getc is called, the StringIOAdapter will return the character at current position and increment the position index. If no more characters are left in the string an EOFError will be raised. The function eof? will return true if the string has run out of characters but otherwise will return false.

To use Encrypter with StringIOAdapter, the reader input object is defined to be of type StringIOAdapter.

encrypter = Encrypter.new('OOLS')
reader= StringIOAdapter.new('TA position open with Prof. XYZ')
writer=File.open('out.txt', 'w')
encrypter.encrypt(reader, writer)

Thus the Adapter bridges the chasm between the interface you have and the interface you need.

The class diagram of Adapter class is usually given as:

The client expects the target to have some interface. But the target is actually an implementation of the Adapter. The Adapter defines a compatible interface while at the same time there is a reference to a second object - the Adaptee - buried inside it. The Adaptee actually performs the work.

Behavioral Patterns

As state earlier, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.<ref>(n.d.). Behavioral patterns. Retrieved from SourceMaking website: http://sourcemaking.com/behavioral_patterns</ref>

Command Pattern

The design patterns we saw above deal with classes and work around the way classes and objects are manipulated, interpreted, created etc. Actually, the adapter pattern bases its necessity on the need for 'code reuse'. But, it can only implement code reuse at a class or method level. But sometimes code must be reused at an even finer level. For example, Sometimes one might need to store bunch of code to be used by a peer or at a later stage. This bunch of code is not associated with any class, or any method.

Command Pattern is useful in such cases. With command pattern it is possible to store a piece of code or a set of commands to be executed at a later stage.

Lets consider a simple example of a GUI button that can be configured to do a variety of actions.<ref>Olsen, R. (2007). Getting things done with commands. In Design patterns in ruby (pp. 147-148). Addison Wesley.</ref> These actions could be saving data to database, making a network connection, navigating to another page, etc.

class UserButton
  attr_accessor :command
  def initialize()
    
  end 
  #
  # Button rendering and management code
  # 
  def on_button_push
    #
    # Do some action
    #
  end 
end

Without the use of the Command Pattern, we could implement a solution here by inheriting the UserButton into subclasses like DatabaseButton, NetworkButton, etc. For example:

class DatabaseButton
  attr_accessor :command
  def initialize()

  end
  #
  # Button rendering and management code
  #
  def on_button_push
    # 
    # Database operations like InsertIntoDatabase(column, value)
    #
  end 
end

This is however a tedious and rigid solution. If suppose on certain button clicks you only wanted to update the database value and not insert. You would either have to create a new subclass with this functionality or check for which operation is required in the on_button_push method and execute separate queries.

The Command Pattern provides an easier way to implement this. The simplest way to implement the Command Pattern in Ruby is through the use of Proc Object with Closures and Blocks.

Consider the following definition for the UserButton class.

class UserButton
  attr_accessor :command
  def initialize(&block)
    @command = block
  end

  #
  # Button rendering and management code
  #

  def on_button_push
    @command.call if @command
  end 
end

Here the @command instance variable is a Proc object. In simple terms, it is a chunk of code that can be executed with the call method.

To instantiate a UserButton for database insertion, a code block is passed when the object is created.

new_button = UserButton.new do
  # 
  # Database operations like InsertIntoDatabase(column, value)
  # or
  # Network link creation
  # or
  # Navigate to another page
  #
end

The class diagram for the Command Pattern is fairly simple. It consists of a number of classes which share the same interface.


An interesting usage of the command pattern is to implement the Undo functionality.<ref>Olsen, R. (2007). Getting things done with commands. In Design patterns in ruby (pp. 151-153). Addison Wesley. </ref> This requires definition of a unexecute method which undoes the actions done in the execute method. A code example can be found here..

Strategy Pattern

The Strategy Pattern helps choose an algorithm to accomplish a task based on some "parameters" of the situation. Also known as the Policy Pattern, it enables selection of algorithms at runtime. This pattern allows the algorithm to vary irresepctive of the user that uses it.

The strategy pattern "defines a family of algorithms, encapsulates each one, and makes them interchangeable".

Consider as an example, a class that that converts among different types of file formats like jpeg, gif, png etc. A case statement can be used to choose what algorithm has to be employed for each type of format. Another example could be performing validation on incoming data, where selection of a validation algorithm is based on the type and source of data.

A Strategy Pattern is best implemented using Proc Objects. An example<ref name = 'multiple'>Olsen, R. (2007). Chapter: 4. replacing the algorithm with the strategy. In Design patterns in ruby (pp. 78-109). Addison Wesley. </ref> of the Strategy Pattern which deals with formatting styles of the report:

class Report
    attr_reader :title, :text
    attr_accessor :formatter
    def initialize(formatter)
         #Initialize title and text
         @formatter = formatter
    end
   end

class Formatter
 def output_report( title, text )
  raise 'Abstract method called'
 end
end

class HTMLFormatter < Formatter
 def output_report( title, text )
  puts('<html>')
  #More HTML formatting code
  puts('</html>')
 end
end

class PlainTextFormatter < Formatter
 def output_report(title, text)
   #More Plain Test formatting code
   puts(line)
 end
end

The above snippet depicts the structure of the Report class, Formatter class(super class), HtmlFormatter class and PlainTextFormatter class(subclasses of Formatter class). The Report class' initialize method invokes the particular formatter class depending upon the formatter specified. These formatter invocations are not specified in advance, hence the Report class has to choose the required formatter function at the run time.

if(type == :HTML)
report = Report.new(HTMLFormatter.new) #HTML Formatter
else
report = Report.new(PlainTextFormatter.new) #formatter type changed to Plain Text Formatter
 
report.output_report # HTML/Plaintext (depends on type variable) Formatter method

The Strategy pattern is based on composition and delegation, rather than on inheritance, hence it is easy to switch strategies at runtime. Thus the path or strategy chosen is based on the formatter invocation on runtime.Therefore, the algorithm that will be selected for displaying the text, is decided at run time.

Illustrated below is the class diagram of Strategy Pattern Design:

The GoF call this “pull the algorithm out into a separate object” technique the Strategy pattern (above Figure). The context class is the class that uses Strategy encapsulation. The Strategy1 and Strategy2 are strategies that get actually chosen by context class. The key idea underlying the Strategy pattern is to define a family of objects, the strategies, which all do the same thing— in given example, format the report. Not only does each strategy object perform the same job, but all of the objects support exactly the same interface. In given example, both of the strategy objects support the output_report method. For more on Strategy Pattern, read the reference book<ref name = 'multiple'>Olsen, R. (2007). Chapter: 4. replacing the algorithm with the strategy. In Design patterns in ruby (pp. 78-109). Addison Wesley. </ref>.

Differences between Command and Strategy Pattern

  • A Command Pattern encapsulates a single action. A command object has a single method with a generic signature associated with it.
  • A Strategy Pattern, enables us to customize an algorithm, deciding which algorithm has to be made use of depending on a number of dynamically changing factors. A given strategy has many methods associated with it.

Comparison of the different Design Patterns

Comparison Factor Singleton Pattern Adapter Pattern Command Pattern Strategy Pattern
Intent Ensure only one object of a class is instantiated, provide a global point of access to that object Convert the interface of a class into one that the client expects Encapsulate a request in an object and allow the parametrization of clients with different requests Encapsulate a set of algorithms and use them interchangeably.
Advantages Helps achieve serialization and is useful in scenarios of logging, communication and lazy instantiations Enables classes to communicate which otherwise would not be able to due to incompatible interfaces. Addition of new functionality is fairly simple as it just calls for encapsulating the functionality into the Command Object. Large conditional statements are eliminated which makes it easy to keep track of the different behaviors which are now in separate classes.
Disadvantages Brings in the concept of global state, making unit testing difficult. Also reduces the scope of parallelism within the program. When using Object Adapters, all the code for delegating all the necessary requests to the Adaptee has to be written. The increase in the number of Command Classes, clutters up the design. The increase in the number of objects, and all the algorithms use the same interface.

See Also

References

<references /> The old wiki can be found at http://expertiza.csc.ncsu.edu/wiki/index.php/CSC/ECE_517_Fall_2011/ch4_4h_sv