CSC/ECE 517 Fall 2011/ch4 4h sv

From Expertiza_Wiki
Jump to navigation Jump to search

Design Patterns in Ruby

Singleton Pattern

The Singleton design pattern is used to restrict the instantiation of a class to only one instance which is globally available. This is used in situations where a user needs an instance of the class to be available in various parts of the application, being available for logging functionality, communictaion with external systems and database access etc. 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.

Below is an illustration of the implementation of Singleton Design Pattern in Ruby:

class Logger
 def initialize
   @log = File.open("log.txt", "a")
 end
  
 @@instance = Logger.new

 def self.instance
   return @@instance
 end

 def log(msg)
   @log.puts(msg)
 end

 private_class_method :new
end

Logger.instance.log('message 1')

In this code example, inside class Logger we create instance of the very same class Logger and we can access that instance with class method Logger.instance whenever we need to write something to the log file using the instance method "log". In the initialize method we just opened a log file for appending, and at the end of Logger class, we made method "new" private so that we cannot create new instances of class Logger. And, that is Singleton Pattern: only one instance, globally available.

require 'singleton'
class Example
include Singleton
attr_accessor :val
end
r = Registry.new #throws a NoMethodError
r = Registry.instance
r.val = 5
s = Registry.instance
puts s.val >>
s.val = 6
puts r.val >>
s.dup >>

Adapter Pattern

An adapter allows classes to work together that normally could not because of incompatible interfaces.

  • It “wraps” its own interface around the interface of a pre-existing

class. What does this mean?

  • It may also translate data formats from the caller to a form needed by

the callee.

The purpose of an adapter is “to convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.”

Command Pattern

At times, it is needed to pass around code that needs to be executed later. This is achieved by employing the command design pattern which is used to factor out the action code of a class into its own object. The Command Pattern does this as follows:

  • A program needs to issue requests to objects. The code that is doing the requesting doesn’t know what the receiver will be, or what operation will be requested.

This is illustrated using the following example:

One example is a check at a restaurant.

  • The waiter/waitress takes an order from a customer and writes it on a check.
  • The check is then queued for the cook, who prepares the food as requested by the customer.
  • The check is later returned to the server, who uses it to bill the customer.

In this example, the check has nothing to do with the menu. In principle, the same checks could be used at any restaurant.

A Command class holds some subset of the following: an object, a method to be applied to the object, and the arguments to be passed when the method is applied. Ruby’s call method then causes the pieces to come together.

The Command Pattern can be implemented using the Proc objects, which is a callable block of code that closes over the variables in scope when it was created. This gives us a concise implementation of Command Pattern.

Another 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. 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.

Strategy Pattern

The strategy pattern (also known as the policy pattern) is a particular software design pattern, whereby algorithms can be selected at runtime. Formally speaking, the strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.[1] For instance, a class that performs validation on incoming data may use a strategy pattern to select a validation algorithm based on the type of data, the source of the data, user choice, and/or other discriminating factors. These factors are not known for each case until run-time, and may require radically different validation to be performed. The validation strategies, encapsulated separately from the validating object, may be used by other validating objects in different areas of the system (or even different systems) without code duplication. The essential requirement in the programming language is the ability to store a reference to some code in a data structure and retrieve it. This can be achieved by mechanisms such as the native function pointer, the first-class function, classes or class instances in object-oriented programming languages, or accessing the language implementation's internal storage of code via reflection.

References

http://designpatternsinruby.com/section01/article.html