CSC/ECE 517 Fall 2012/ch2a 2w17 pt

From Expertiza_Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Design Pattern

A software design pattern is a problem-solution pair that gives a general re-usable solution to a commonly occurring problem and can be applied in a similar fashion in new contexts. A design pattern is a template that gives a solution to many similar situations. It cannot be directly transformed into code. The solution is usually a simple mechanism because it is a collaboration between two or more classes, objects, services, processes, threads, components, or nodes that work together to solve the underlying architecture or development challenge Design patterns documents simple mechanism that work. They provide a common vocabulary and taxonomy for developers and architects. They allow solutions to be described concisely as combinations of patterns. They enable reuse of architecture, design, and implementation decisions. All these features make design patterns very useful to software developers and architects. Design patterns are typically represented as relationships between classes and objects with defined responsibilities that act in concert to carry out the solution. For instance consider the Adapter pattern provides a solution to the scenario in which a client and server need to interact with one another, but cannot because their interfaces are not compatible. To implement the Adapter pattern, you create a custom class that honors the interface provided by the server and defines the server operations in terms the client expects. This is a much better solution than altering the client to match the interface of the server. There are many design patterns like Algorithm strategy patterns, Computational design patterns, Execution patterns, Implementation strategy patterns, Structural design patterns.

Proxy pattern

The Proxy pattern, also known as a surrogate pattern, is a Structural design pattern. A proxy provides a surrogate or placeholder for another object to control access to it. There will be situations in which a client does not or cannot reference an object directly but still wants to interact with the object. A proxy object can act as an intermediary between the client and the target object. A proxy object has the same interface as the target object. The proxy holds a reference to the target object and can forward requests to the target as required. In effect, the proxy object has the authority to act on behalf of the client to interact with the target object.

UML Class Diagram

By defining a Subject interface, the presence of the Proxy object standing in place of the RealSubject is transparent to the client.

Applications of Proxy Pattern

  • A proxy can interface a network connection, a large object in memory, a file or any other resource that is expensive or impossible to duplicate.
  • Proxies are useful wherever there is a need for a more sophisticated reference to a object than a simple pointer or simple reference can provide.
  • In situations where multiple copies of a complex object must exist, the proxy pattern can be used to reduce the application’s memory requirements. A single instance of the complex object and multiple proxy objects are created all of which are references to the original complex object. Any operation on the proxy is forwarded to the original object.

Types of proxies

Remote Proxy

A remote proxy provides a reference to an object located in a different address space on the same or different machine. They are responsible for encoding a request and its arguments and for sending the encoded request to the real subject in a different address space.

Virtual Proxy

A virtual proxy allows the creation of a memory intensive object on demand. The object will not be created until it is really needed.

Copy-on-Write Proxy

A copy-on-write defers cloning a target object until required by client actions. It is really a form of virtual proxy.

Protection Proxy

A protection proxy provides different clients with different levels of access to a target object.

Cache Proxy

A cache proxy provides temporary storage of the results of expensive target operations so that multiple clients can share the results.

Firewall Proxy

A firewall proxy protects targets from bad clients (or vice versa).

Synchronization Proxy

A synchronization proxy provides multiple accesses to a target object.

Smart reference Proxy

A smart reference proxy provides additional actions whenever a target object is referenced such as counting the number of references to the object.

Examples of Proxy pattern

C++

Example 1

class RealImage
{
    int m_id;
    public:
    RealImage(int i)
    {
       m_id = i;
       cout << "   $$ ctor: " << m_id << '\n';
    }
   ~RealImage()
   {
       cout << "   dtor: " << m_id << '\n';
   }
   void draw()
   {
       cout << "   drawing image " << m_id << '\n';
   }
};
// 1. Design an "extra level of indirection" wrapper class
class Image
{
   // 2. The wrapper class holds a pointer to the real class
   RealImage *m_the_real_thing;
   int m_id;
   static int s_next;
 public:
   Image()
   {
       m_id = s_next++;
       // 3. Initialized to null
       m_the_real_thing = 0;
   }
   ~Image()
   {
       delete m_the_real_thing;
   }
   void draw()
   {
       // 4. When a request comes in, the real object is
       //    created "on first use"
       if (!m_the_real_thing)
         m_the_real_thing = new RealImage(m_id);
       // 5. The request is always delegated
       m_the_real_thing->draw();
   }
};
int Image::s_next = 1;
int main()
{
 Image images[5];
 for (int i; true;)
 {
   cout << "Exit[0], Image[1-5]: ";
   cin >> i;
   if (i == 0)
     break;
   images[i - 1].draw();
 }
}

Explanation of Proxy Pattern

  • The Wrapper class has an extra level on indirection
  • The Wrapper class contains a pointer to the original class and it is initialized to NULL
  • Lazy initialization is implemented.
  • Request is always delegated.

Output

Exit[0], Image[1-5]: 2 
$$ ctor: 2 drawing image 2 
Exit[0], Image[1-5]: 4 
$$ ctor: 4 drawing image 4 
Exit[0], Image[1-5]: 2 
drawing image 2 
Exit[0], Image[1-5]: 0 
dtor: 4 
dtor: 2

Exmaple 2

class Subject
{
 public:
   virtual void execute() = 0;
};
class RealSubject: public Subject
{
   string str;
 public:
   RealSubject(string s)
   {
       str = s;
   }
    /*virtual*/void execute()
   {
       cout << str << '\n';
   }
};
class ProxySubject: public Subject
{
   string first, second, third;
   RealSubject *ptr;
 public:
   ProxySubject(string s)
   {
       int num = s.find_first_of(' ');
       first = s.substr(0, num);
       s = s.substr(num + 1);
       num = s.find_first_of(' ');
       second = s.substr(0, num);
       s = s.substr(num + 1);
       num = s.find_first_of(' ');
       third = s.substr(0, num);
       s = s.substr(num + 1);
       ptr = new RealSubject(s);
   }
   ~ProxySubject()
   {
       delete ptr;
   }
   RealSubject *operator->()
   {
       cout << first << ' ' << second << ' ';
       return ptr;
   }
    /*virtual*/void execute()
   {
       cout << first << ' ' << third << ' ';
       ptr->execute();
   }
};
int main()
{
 ProxySubject obj(string("the quick brown fox jumped over the dog"));
 obj->execute();
 obj.execute();
}

Explanation of Proxy Pattern

  • Here ”->” and “.” operators give different results.

Output

the quick fox jumped over the dog 
the brown fox jumped over the dog

Java

import java.io.*;  import java.net.*;
// 5. To be compatible, an interface is created between the proxy and target
interface SocketInterface {
 String readLine();
 void  writeLine( String str );
 void  dispose();
}
public class ProxyDemo {
 public static void main( String[] args ) {
   // 3. The client deals with the proxy
   SocketInterface socket = new SocketProxy( "127.0.0.1", 8189,
     args[0].equals("first") ? true : false );
   String  str = null;
   boolean skip = true;
   while (true) {
     if (args[0].equals("second")  &&  skip) {
       skip = ! skip;
     }
     else {
       str = socket.readLine();
       System.out.println( "Receive - " + str );  // java ProxyDemo first
       if (str.equals("quit")) break;             // Receive - 123 456
     }                                            // Send ---- 234 567
     System.out.print( "Send ---- " );            // Receive - 345 678
     str = Read.aString();                        //
     socket.writeLine( str );                     // java ProxyDemo second
     if (str.equals("quit")) break;               // Send ---- 123 456
   }                                              // Receive - 234 567
   socket.dispose();                              // Send ---- 345 678
 }
}
class SocketProxy implements SocketInterface {
 // 1. A proxy is created for the expensive or remote or sensitive object(target)
 private Socket      socket;
 private BufferedReader in;
 private PrintWriter   out;
 public SocketProxy( String host, int port, boolean wait ) {
   try {
     if (wait) {
       // 2. A level of abstraction is created to encapsulate the complexity is the target
       ServerSocket server = new ServerSocket( port );
       socket = server.accept();
     } else
       socket = new Socket( host, port );
       in  = new BufferedReader( new InputStreamReader(
                                       socket.getInputStream()));
       out = new PrintWriter( socket.getOutputStream(), true );
     } catch( IOException e ) {
       e.printStackTrace();
     }
 }
 public String readLine() {
   String str = null;
   try {
     str = in.readLine();
   } catch( IOException e ) {
     e.printStackTrace();
   }
   return str;
 }
 public void writeLine( String str ) {
   // 4. The proxy delegates the target
   out.println( str );
 }
 public void dispose() {
   try {
     socket.close();
   } catch( IOException e ) {
     e.printStackTrace();
   }
 }
}

Explanation of Proxy Pattern

  • A proxy is created for the expensive or remote or sensitive object(target)
  • A level of abstraction is created to encapsulate the complexity is the target
  • The client deals with the proxy
  • The proxy delegates the target
  • To be compatible, an interface is created between the proxy and target.

C#

using System;
 // MainApp test application 
 class MainApp
 {
   static void Main()
   {
     // Create proxy and request a service 
     Proxy proxy = new Proxy();
     proxy.Request();
     // Wait for user 
     Console.Read();
   }
 }
 // "Subject" 
 abstract class Subject 
 {
   public abstract void Request();    
 }
 // "RealSubject" 
 class RealSubject : Subject
 {
   public override void Request()
   {
     Console.WriteLine("Called RealSubject.Request()");
   }
 }
 // "Proxy" 
 class Proxy : Subject
 {
   RealSubject realSubject;
   public override void Request()
   {
     // Use 'lazy initialization' 
     if (realSubject == null)
     {
       realSubject = new RealSubject();
     }
     realSubject.Request();
   }  
 }

Explanation of Proxy Pattern

  • A surrogate is provided for another object to control access to it.

Output

Called RealSubject.Request()

PHP

<?php
class ProxyBookList {
   private $bookList = NULL; 
   //bookList is not instantiated at construct time
   function __construct() {
   }
   function getBookCount() {
       if (NULL == $this->bookList) {
           $this->makeBookList(); 
       }
       return $this->bookList->getBookCount();
   }
   function addBook($book) {
       if (NULL == $this->bookList) {
           $this->makeBookList(); 
       }
       return $this->bookList->addBook($book);
   }  
   function getBook($bookNum) {
       if (NULL == $this->bookList) {
           $this->makeBookList();
       } 
       return $this->bookList->getBook($bookNum);
   }
   function removeBook($book) {
       if (NULL == $this->bookList) {
           $this->makeBookList();
       } 
       return $this->bookList->removeBook($book);
   }
   //Create 
   function makeBookList() {
       $this->bookList = new bookList();
   }
}
class BookList {
   private $books = array();
   private $bookCount = 0;
   public function __construct() {
   }
   public function getBookCount() {
       return $this->bookCount;
   }
   private function setBookCount($newCount) {
       $this->bookCount = $newCount;
   }
   public function getBook($bookNumberToGet) {
       if ( (is_numeric($bookNumberToGet)) && ($bookNumberToGet <= $this->getBookCount())) {
           return $this->books[$bookNumberToGet];
       } else {
          return NULL;
       }
   }
   public function addBook(Book $book_in) {
       $this->setBookCount($this->getBookCount() + 1);
       $this->books[$this->getBookCount()] = $book_in;
       return $this->getBookCount();
   }
   public function removeBook(Book $book_in) {
       $counter = 0;
       while (++$counter <= $this->getBookCount()) {
         if ($book_in->getAuthorAndTitle() == $this->books[$counter]->getAuthorAndTitle()) {
           for ($x = $counter; $x < $this->getBookCount(); $x++) {
             $this->books[$x] = $this->books[$x + 1];
         }
         $this->setBookCount($this->getBookCount() - 1);
       }
     }
     return $this->getBookCount();
   }
}
class Book {
   private $author;
   private $title;
   function __construct($title_in, $author_in) {
     $this->author = $author_in;
     $this->title  = $title_in;
   }
   function getAuthor() {
       return $this->author;
   }
   function getTitle() {
       return $this->title;
   }
   function getAuthorAndTitle() {
     return $this->getTitle().' by '.$this->getAuthor();
   }
}
 writeln( 'BEGIN TESTING PROXY PATTERN';
 writeln();
 $proxyBookList = new ProxyBookList();
 $inBook = new Book('PHP for Cats','Larry Truett');
 $proxyBookList->addBook($inBook);
 writeln('test 1 - show the book count after a book is added');
 writeln($proxyBookList->getBookCount());
 writeln();
 writeln('test 2 - show the book');
 $outBook = $proxyBookList->getBook(1);
 writeln($outBook->getAuthorAndTitle()); 
 writeln();
 $proxyBookList->removeBook($outBook);
 writeln('test 3 - show the book count after a book is removed');
 writeln($proxyBookList->getBookCount());
 writeln();
 writeln('END TESTING PROXY PATTERN');
 function writeln($line_in) {
   echo $line_in."
"; } ?>

Explanation of Proxy Pattern

  • ProxyBookList is created in place of the more resource intensive BookList. ProxyBookList will only instantiate BookList the first time a method in BookList is called.

Output

BEGIN TESTING PROXY PATTERN 
test 1 - show the book count after a book is added 
1 
test 2 - show the book 
PHP for Cats by Larry Truett 
test 3 - show the book count after a book is removed 
0 
END TESTING PROXY PATTERN

Similar patterns

Adapter Pattern

An adapter pattern translates one interface for a class into a compatible interface. An adapter allows classes to work together that normally could not because of incompatible interfaces, by providing its interface to clients while using the original interface

Bridge Pattern

A Bridge Pattern decouples an abstraction from its implementation so that the two can vary independently". The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.

Composite Pattern

A composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects are to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.

Decorator Pattern

The decorator pattern can be used to extend (decorate) the functionality of a certain object dynamically, independently of other instances of the same class, provided some groundwork is done at design time. This is achieved by designing a new decorator class that wraps the original class.

Facade Pattern

A facade is an object that provides a simplified interface to a larger body of code, such as a class library. A facade can make a software library easier to use, understand and test, since the facade has convenient methods for common tasks. It can make the library more readable, for the same reason. It can reduce dependencies of outside code on the inner workings of a library, since most code uses the facade, thus allowing more flexibility in developing the system. It wraps a poorly designed collection of API’s with a single well-designed API .

Flyweight Pattern

A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory. Often some parts of the object state can be shared, and it is common practice to hold them in external data structures and pass them to the flyweight objects temporarily when they are used.

Front Controller Pattern

Front controllers are often used in web applications to implement workflows. While not strictly required, it is much easier to control navigation across a set of related pages (for instance, multiple pages might be used in an online purchase) from a front controller than it is to make the individual pages responsible for navigation.

Module Pattern

A module pattern is a design pattern used to implement the concept of software modules, defined by modular programming, in a programming language that does not support it, or only supports it, partially.

Comparisons

Comparison of Proxy pattern and Facade Pattern

  • The proxy pattern adds behavior whereas the façade pattern simplifies behavior.
  • Proxies are optional, facades are not.

Comparison of Adapter Pattern and Facade Pattern

  • In adapter pattern, the interface that is being adapted might already exist.
  • The adapter pattern preserves polymorphism. A façade provides an idealized flexible interface which can be modified anytime as requirements come in.
  • Adapters are usually small and hence do not have performance issues whereas facades are huge.

Comparison of Proxy pattern and Adapter pattern

  • An adapter pattern changes the interface of the service whereas proxy pattern changes the behavior.
  • An adapter pattern preserves the behavior of the service whereas the proxy pattern preserves the interface.
  • In adapter pattern client can use the service entity only by using the adapter whereas in proxy pattern a client can use the proxy or the adapter in the same way.
  • The Proxy can be cast to the interface of the Service. The Adapter can be cast to the interface the Client expects.

Comparison of Bridge pattern and Adapter pattern

  • An adapter pattern changes the interface of the service whereas proxy pattern changes the behavior.
  • A Bridge Pattern decouples an abstraction from its implementation so that the two can vary independently". The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.
  • Bridge pattern serves to decouple an abstraction class from its implementation, where as an adaptor pattern converts between classes with less inheritance
  • One main difference according to GOF is that "Adapter makes things work after they're designed; Bridge makes them work before they are"

Comparison of Decorator pattern and Facade pattern

  • Facade gives the impression that your create a facade object over different desperate objects, or you actually decorate them with another layer, or they are two different name for the same pattern
  • Decorator pattern is a design pattern that allows new/additional behavior to be added to an existing class dynamically, it also provides a flexible alternative to sub classing for extending functionality.
  • Facade is more like a simple gateway to a complicated set of functionality. You make a black-box for your clients to worry less i.e. make interfaces simpler
  • Where as decorator is used to add more gunpowder to your objects (note the term objects -- you typically decorate objects dynamically at runtime). You do not hide/impair the existing interfaces of the object but simply extend it at runtime.

Comparison of Composite pattern and Decorator pattern

  • The composite pattern allows you to build a hierarchical structure (such as a tree of elements) in a way that allows your external code to view the entire structure as a single entity. So the interface to a leaf entity is exactly the same as the entity for a compound entity.
  • The decorator pattern allows an entity to completely contain another entity so that using the decorator looks identical to the contained entity. This allows the decorator to modify the behavior and/or content of whatever it is encapsulating without changing the outward appearance of the entity
  • Composite pattern: gives an unified interface to a leaf and composite.
  • Decorator: composite gives additional feature to leaf, while giving unified interface.

References