CSC/ECE 517 Fall 2012/ch2a 2w17 pt

From PG_Wiki
Jump to: navigation, search

Contents

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

Pt.jpg

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

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

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

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

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

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

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

Comparison of Adapter Pattern and Facade Pattern

Comparison of Proxy pattern and Adapter pattern

Comparison of Bridge pattern and Adapter pattern

Comparison of Decorator pattern and Facade pattern

Comparison of Composite pattern and Decorator pattern

References

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox