Monday, August 31, 2009

Structural Design Pattern

Structural Design Patterns:

Adapter Pattern

Motivation

The adapter pattern is adapting between classes and objects. Like any adapter in the real world it is used to be an interface, a bridge between two objects. In real world we have adapters for power supplies, adapters for camera memory cards, and so on. Probably everyone have seen some adapters for memory cards. If you can not plug in the camera memory in your laptop you can use and adapter. You plug the camera memory in the adapter and the adapter in to laptop slot. That's it, it's really simple.
What about software development? It's the same. Can you imagine an situation when you have some class expecting some type of object and you have an object offering the same features, but exposing a different interface? Of course, you want to use both of them so you don't to implement again one of them, and you don't want to change existing classes, so why not create an adapter...

Intent

·         Convert the interface of a class into another interface clients expect.
·         Adapter lets classes work together, that could not otherwise because of incompatible interfaces.

Implementation

The figure below shows a UML class diagram for the Adapter Pattern:
Adapter  Pattern Implementation - UML Class Diagram

The classes/objects participating in adapter pattern:
·         Target - defines the domain-specific interface that Client uses.
·         Adapter - adapts the interface Adaptee to the Target interface.
·         Adaptee - defines an existing interface that needs adapting.
·         Client - collaborates with objects conforming to the Target interface.

Applicability & Examples

The visitor pattern is used when:
·         When you have a class(Target) that invokes methods defined in an interface and you have a another class(Adapter) that doesn't implement the interface but implements the operations that should be invoked from the first class through the interface. You can change none of the existing code. The adapter will implement the interface and will be the bridge between the 2 classes.
·         When you write a class (Target) for a generic use relying on some general interfaces and you have some implemented classes, not implementing the interface, that needs to be invoked by the Target class.

Adapters are encountered everywhere. From real world adapters to software adapters

·         Non Software Examples of Adapter Patterns : Power Supply Adapters, card readers and adapters, ... Software Examples of Adapter Patterns: Wrappers used to adopt 3rd parties libraries and frameworks - most of the applications using third party libraries use adapters as a middle layer between the application and the 3rd party library to decouple the application from the library. If another library has to be used only an adapter for the new library is required without having to change the application code.

Specific problems and implementation

Objects Adapters - Based on Delegation

Objects Adapters are the classical example of the adapter pattern. It uses composition, the Adaptee delegates the calls to Adaptee (opossed to class adapters which extends the Adaptee). This behaviour gives us a few advantages over the class adapters(however the class adapters can be implemented in languages allowing multiple inheritance). The main advantage is that the Adapter adapts not only the Adpatee but all its subclasses. All it's subclasses with one "small" restriction: all the subclasses which don't add new methods, because the used mechanism is delegation. So for any new method the Adapter must be changed or extended to expose the new methods as well. The main disadvantage is that it requires to write all the code for delegating all the necessary requests tot the Adaptee.

 

 

 

 

 

Class Adapters - Based on (Multiple) Inheritance

Adapter  Pattern Implementation - UML Class Diagram
Class adapters can be implemented in languages supporting multiple inheritance(Java, C# or PHP does not support multiple inheritance). Thus, such adapters can not be easy implemented in Java, C# or VB.NET. Class adapter uses inheritance instead of composition. It means that instead of delegating the calls to the Adaptee, it subclasses it. In conclusion it must subclass both the Target and the Adaptee. There are advantages and disadvantages:
·         It adapts the specific Adaptee class. The class it extends. If that one is subclassed it can not be adapted by the existing adapter.
·         It doesn't require all the code required for delegation, which must be written for an Object Adapter.
If the Target is represented by an interface instead of a class then we can talk about "class" adapters, because we can implement as many interfaces as we want.

How Much the Adapter Should Do?

This question has a really simple response: it should do how much it has to in order to adapt. It's very simple, if the Target and Adaptee are similar then the adapter has just to delegate the requests from the Target to the Adaptee. If Target and Adaptee are not similar, then the adapter might have to convert the data structures between those and to implement the operations required by the Target but not implemented by the Adaptee.

Two-Ways Adapters

The Two-Ways Adapters are adapters that implements both interfaces of Target and Adaptee. The adapted object can be used as Target in new systems dealing with Target classes or as Adaptee in other systems dealing with Adaptee classes. Going further on this line of thinking, we can have adapters implementing n interfaces, adapting to n systems. Two-way adapters and n-way adapters are hard to implement in systems not supporting multiple inheritance. If adapter has to extend the Target class it can not extent another class like Adaptee, so the Adaptee should be an interface and all the calls should be delegated from the adapter to the Adaptee object.

Adapter Pattern and Strategy Pattern

Adapter Pattern and Strategy Pattern - there are many cases when the adapter can play the role of the Strategy Pattern. If we have several modules implementing the same functionality and we wrote adapters for them, the adapters are implementing the same interface. We can simply replace the adapters objects at run time because they implements the same interface.

Bridge Pattern

Motivation

Sometimes an abstraction should have different implementations; consider an object that handles persistence of objects over different platforms using either relational databases or file system structures (files and folders). A simple implementation might choose to extend the object itself to implement the functionality for both file system and RDBMS. However this implementation would create a problem; Inheritance binds an implementation to the abstraction and thus it would be difficult to modify, extend, and reuse abstraction and implementation independently.

Intent

·         The intent of this pattern is to decouple abstraction from implementation so that the two can vary independently.

Implementation

The figure below shows a UML class diagram for the Bridge Pattern:
Bridge Pattern Implementation - UML Class Diagram
The participants classes in the bridge pattern are:

·         Abstraction - Abstraction defines abstraction interface.

·         AbstractionImpl - Implements the abstraction interface using a reference to an object of type Implementor.

·         Implementor - Implementor defines the interface for implementation classes. This interface does not need to correspond directly to abstraction interface and can be very different. Abstraction imp provides an implementation in terms of operations provided by Implementor interface.

·         ConcreteImplementor1, ConcreteImplementor2 - Implements the Implementor interface.

Description

An Abstraction can be implemented by an abstraction implementation, and this implementation does not depend on any concrete implementers of the Implementor interface. Extending the abstraction does not affect the Implementor. Also extending the Implementor has no effect on the Abstraction.

Applicability & Examples

The bridge pattern applies when there is a need to avoid permanent binding between an abstraction and an implementation and when the abstraction and implementation need to vary independently. Using the bridge pattern would leave the client code unchanged with no need to recompile the code.

Example - Object Persistence API Example

As discussed previously a persistence API can have many implementations depending on the presence or absence of a relational database, a file system, as well as on the underlying operating system.
Bridge Pattern Example - UML Class Diagram

Specific problems and implementation

Graphical User Interface Frameworks

Graphical User Interface Frameworks use the bridge pattern to separate abstractions from platform specific implementation. For example GUI frameworks separate a Window abstraction from a Window implementation for Linux or Mac OS using the bridge pattern.

Related Patterns

·         Abstract Factory Pattern - An Abstract Factory pattern can be used create and configure a particular Bridge, for example a factory can choose the suitable concrete implementor at runtime.

Consequences

Known Uses:
·         Decoupling interface and implementation. An implementation is not bound permanently to an interface. The implementation of an abstraction can be configured and even switched at run-time.
·         Abstraction and Implementor hierarchies can be extended independently.

Known Uses:

·         GUI frameworks as discussed previously.
·         Persistence Frameworks as discussed previously.

 Composite Pattern

Motivation

There are times when a program needs to manipulate a tree data structure and it is necessary to treat both Branches as well as Leaf Nodes uniformly. Consider for example a program that manipulates a file system. A file system is a tree structure that contains Branches which are Folders as well as Leaf nodes which are Files. Note that a folder object usually contains one or more file or folder objects and thus is a complex object where a file is a simple object. Note also that since files and folders have many operations and attributes in common, such as moving and copying a file or a folder, listing file or folder attributes such as file name and size, it would be easier and more convenient to treat both file and folder objects uniformly by defining a File System Resource Interface.

Intent

·         The intent of this pattern is to compose objects into tree structures to represent part-whole hierarchies.
·         Composite lets clients treat individual objects and compositions of objects uniformly.

Implementation

The figure below shows a UML class diagram for the Composite Pattern:
Composite Pattern Implementation - UML Class Diagram
·         Component - Component is the abstraction for leafs and composites. It defines the interface that must be implemented by the objects in the composition. For example a file system resource defines move, copy, rename, and getSize methods for files and folders.

·         Leaf - Leafs are objects that have no children. They implement services described by the Component interface. For example a file object implements move, copy, rename, as well as getSize methods which are related to the Component interface.

·         Composite - A Composite stores child components in addition to implementing methods defined by the component interface. Composites implement methods defined in the Component interface by delegating to child components. In addition composites provide additional methods for adding, removing, as well as getting components.

·         Client - The client manipulates objects in the hierarchy using the component interface.
A client has a reference to a tree data structure and needs to perform operations on all nodes independent of the fact that a node might be a branch or a leaf. The client simply obtains reference to the required node using the component interface, and deals with the node using this interface; it doesn’t matter if the node is a composite or a leaf.

Applicability & Examples

The composite pattern applies when there is a part-whole hierarchy of objects and a client needs to deal with objects uniformly regardless of the fact that an object might be a leaf or a branch.

Example - Graphics Drawing Editor.

In graphics editors a shape can be basic or complex. An example of a simple shape is a line, where a complex shape is a rectangle which is made of four line objects. Since shapes have many operations in common such as rendering the shape to screen, and since shapes follow a part-whole hierarchy, composite pattern can be used to enable the program to deal with all shapes uniformly.

In the example we can see the following actors:

·         Shape (Component) - Shape is the abstraction for Lines, Rectangles (leafs) and and ComplexShapes (composites).

·         Line, Rectangle (Leafs) - objects that have no children. They implement services described by the Shape interface.

·         ComplexShape (Composite) - A Composite stores child Shapes in addition to implementing methods defined by the Shape interface.

·         GraphicsEditor (Client) - The GraphicsEditor manipulates Shapes in the hierarchy.

Alternative Implementation: Note that in the previous example there were times when we have avoided dealing with composite objects through the Shape interface and we have specifically dealt with them as composites (when using the method addToShape()). To avoid such situations and to further increase uniformity one can add methods to add, remove, as well as get child components to the Shape interface. The UML diagram below shows it:
Composite Pattern Alternative Implementation - UML Class Diagram

Specific problems and implementation

Graphics Editors use composite pattern to implement complex and simple graphics as previously explained.
File System implementations use the composite design pattern as described previously.

Consequences

·         The composite pattern defines class hierarchies consisting of primitive objects and composite objects. Primitive objects can be composed into more complex objects, which in turn can be composed.
·         Clients treat primitive and composite objects uniformly through a component interface which makes client code simple.
·         Adding new components can be easy and client code does not need to be changed since client deals with the new components through the component interface.

Related Patterns

Decorator Pattern - Decorator is often used with Composite. When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface with operations like Add, Remove, and GetChild.

Known Uses

File System Implementation as discussed previously.
Graphics Editors as discussed previously.

Decorator Pattern

Motivation

Extending an object’s functionality can be done statically (at compile time) by using inheritance however it might be necessary to extend an object’s functionality dynamically (at runtime) as an object is used.
Consider the typical example of a graphical window. To extend the functionality of the graphical window for example by adding a frame to the window, would require extending the window class to create a FramedWindow class. To create a framed window it is necessary to create an object of the FramedWindow class. However it would be impossible to start with a plain window and to extend its functionality at runtime to become a framed window.

Intent

·         The intent of this pattern is to add additional responsibilities dynamically to an object.

Implementation

The figure below shows a UML class diagram for the Decorator Pattern:
The participants classes in the decorator pattern are:

·         Component - Interface for objects that can have responsibilities added to them dynamically.

·         ConcreteComponent - Defines an object to which additional responsibilities can be added.

·         Decorator - Maintains a reference to a Component object and defines an interface that conforms to Component's interface.

·         Concrete Decorators - Concrete Decorators extend the functionality of the component by adding state or adding behavior.

Description

The decorator pattern applies when there is a need to dynamically add as well as remove responsibilities to a class, and when subclassing would be impossible due to the large number of subclasses that could result.

Applicability & Examples

Example - Extending capabilities of a Graphical Window at runtime

Decorator Pattern Example - UML Class Diagram
In Graphical User Interface toolkits windows behaviors can be added dynamically by using the decorator design pattern.

Specific problems and implementation

Graphical User Interface Frameworks

GUI toolkits use decoration pattern to add functionalities dynamically as explained before.

 

Related Patterns

·         Adapter Pattern - A decorator is different from an adapter in that a decorator changes object's responsibilities, while an adapter changes an object interface.

·         Composite Pattern - A decorator can be viewed as a degenerate composite with only one component. However, a decorator adds additional responsibilities.

Consequences

·         Decoration is more convenient for adding functionalities to objects instead of entire classes at runtime. With decoration it is also possible to remove the added functionalities dynamically.
·         Decoration adds functionality to objects at runtime which would make debugging system functionality harder.

Known Uses:

·         GUI toolkits as has been previously explained.

 FlyWeight Pattern

Motivation

Some programs require a large number of objects that have some shared state among them. Consider for example a game of war, were there is a large number of soldier objects; a soldier object maintain the graphical representation of a soldier, soldier behavior such as motion, and firing weapons, in addition soldier’s health and location on the war terrain. Creating a large number of soldier objects is a necessity however it would incur a huge memory cost. Note that although the representation and behavior of a soldier is the same their health and location can vary greatly.

Intent

·         The intent of this pattern is to use sharing to support a large number of objects that have part of their internal state in common where the other part of state can vary.

 

 

 

Implementation

The figure below shows a UML class diagram for the Flyweight Pattern:
Flyweight Pattern Implementation - UML Class Diagram
·         Flyweight - Declares an interface through which flyweights can receive and act on extrinsic state.

·         ConcreteFlyweight - Implements the Flyweight interface and stores intrinsic state. A ConcreteFlyweight object must be sharable. The Concrete flyweight object must maintain state that it is intrinsic to it, and must be able to manipulate state that is extrinsic. In the war game example graphical representation is an intrinsic state, where location and health states are extrinsic. Soldier moves, the motion behavior manipulates the external state (location) to create a new location.

·         FlyweightFactory - The factory creates and manages flyweight objects. In addition the factory ensures sharing of the flyweight objects. The factory maintains a pool of different flyweight objects and returns an object from the pool if it is already created, adds one to the pool and returns it in case it is new.
In the war example a Soldier Flyweight factory can create two types of flyweights : a Soldier flyweight, as well as a Colonel Flyweight. When the Client asks the Factory for a soldier, the factory checks to see if there is a soldier in the pool, if there is, it is returned to the client, if there is no soldier in pool, a soldier is created, added to pool, and returned to the client, the next time a client asks for a soldier, the soldier created previously is returned, no new soldier is created.

·         Client - A client maintains references to flyweights in addition to computing and maintaining extrinsic state
A client needs a flyweight object; it calls the factory to get the flyweight object. The factory checks a pool of flyweights to determine if a flyweight object of the requested type is in the pool, if there is, the reference to that object is returned. If there is no object of the required type, the factory creates a flyweight of the requested type, adds it to the pool, and returns a reference to the flyweight. The flyweight maintains intrinsic state (state that is shared among the large number of objects that we have created the flyweight for) and provides methods to manipulate external state (State that vary from object to object and is not common among the objects we have created the flyweight for).

 

Applicability & Examples

The flyweight pattern applies to a program using a huge number of objects that have part of their internal state in common where the other part of state can vary. The pattern is used when the larger part of the object’s state can be made extrinsic (external to that object).

Example - The war game.

The war game instantiates 5 Soldier clients, each client maintains its internal state which is extrinsic to the soldier flyweight. And Although 5 clients have been instantiated only one flyweight Soldier has been used.
Flyweight Pattern Example - UML Class Diagram

Specific problems and implementation

Text Editors

Object oriented text editors need to create Character Objects to represent each character that is in the document. A Character object maintains information about what is the character, what is its font, what is the size of the character, as well as character location inside the document. A document typically consists of extremely large number of character objects which requires large memory. Note that the number of characters in general (Digits, Letters, Other special characters) is known and is fixed, and the fonts that can be applied to each character are also known, thus by creating a Letter flyweight that maintains Character Type (letter, digit, etc…), as well as font, and by creating a Letter Client object that only maintains each character’s location inside the document, we have reduced the editor’s memory requirements drastically.

Consequences

Flyweight pattern saves memory by sharing flyweight objects among clients. The amount of memory saved generally depends on the number of flyweight categories saved (for example a soldier category and a lieutenant category as discussed earlier).

Related Patterns

Factory and Singleton patterns - Flyweights are usually created using a factory and the singleton is applied to that factory so that for each type or category of flyweights a single instance is returned.

State and Strategy Patterns - State and Strategy objects are usually implemented as Flyweights.

Known Uses

Games with graphics as discussed with the War Game Example
Text Editors as discussed in the Text Editors example.
Memento Pattern

Motivation

It is sometimes necessary to capture the internal state of an object at some point and have the ability to restore the object to that state later in time. Such a case is useful in case of error or failure. Consider the case of a calculator object with an undo operation such a calculator could simply maintain a list of all previous operation that it has performed and thus would be able to restore a previous calculation it has performed. This would cause the calculator object to become larger, more complex, and heavyweight, as the calculator object would have to provide additional undo functionality and should maintain a list of all previous operations. This functionality can be moved out of the calculator class, so that an external (let’s call it undo manager class) can collect the internal state of the calculator and save it. However providing the explicit access to every state variable of the calculator to the restore manager would be impractical and would violate the encapsulation principle.

Intent

·         The intent of this pattern is to capture the internal state of an object without violating encapsulation and thus providing a mean for restoring the object into initial state when needed.

Implementation

The figure below shows a UML class diagram for the Memento Pattern:
Memento Pattern Implementation - UML Class Diagram
·         Memento
1.    Stores internal state of the Originator object. The state can include any number of state variables.
2.    The Memento must have two interfaces, an interface to the caretaker. This interface must not allow any operations or any access to internal state stored by the memento and thus honors encapsulation. The other interface is to the originator and allows the originator to access any state variables necessary to for the originator to restore previous state.

·         Originator
1.    Creates a memento object capturing the originators internal state.
2.    Use the memento object to restore its previous state.

·         Caretaker
1.    Responsible for keeping the memento.
2.    The memento is opaque to the caretaker, and the caretaker must not operate on it.
A Caretaker would like to perform an operation on the Originator while having the possibility to rollback. The caretaker calls the createMemento() method on the originator asking the originator to pass it a memento object. At this point the originator creates a memento object saving its internal state and passes the memento to the caretaker. The caretaker maintains the memento object and performs the operation. In case of the need to undo the operation, the caretaker calls the setMemento() method on the originator passing the maintained memento object. The originator would accept the memento, using it to restore its previous state.

Applicability & Examples

The memento pattern is used when a snapshot of an object's state must be captured so that it can be restored to that state later and in situations where explicitly passing the state of the object would violate encapsulation.

Example - Simple Calculator with Undo Operation.

This simple example is a calculator that finds the result of addition of two numbers, with the additional option to undo last operation and restore previous result.
Memento Pattern Alternative Implementation - UML Class Diagram

Specific problems and implementation

Database Transactions

Transactions are operations on the database that occur in an atomic, consistent, durable, and isolated fashion. A transaction can contain multiple operations on the database; each operation can succeed or fail, however a transaction guarantees that if all operations succeed, the transaction would commit and would be final. And if any operation fails, then the transaction would fail and all operations would rollback and leave the database as if nothing has happened.
This mechanism of rolling back uses the memento design pattern. Consider an object representing a database table, a transaction manager object which is responsible of performing transactions must perform operations on the table object while having the ability to undo the operation if it fails, or if any operation on any other table object fails. To be able to rollback, the transaction manager object would ask the table object for a memento before performing an operation and thus in case of failure, the memento object would be used to restore the table to its previous state.

Consequences

Memento protects encapsulation and avoids exposing originator’s internal state and implementation. It also simplifies originator code such that the originator does not need to keep track of its previous state since this is the responsibility of the CareTaker.
Using the memento pattern can be expensive depending on the amount of state information that has to be stored inside the memento object. In addition the caretaker must contain additional logic to be able to manage mementos.

Related Patterns

Command Pattern - Commands can use mementos to maintain state for undoable operations.

Known Uses

Undo and restore operations in most software.
Database transactions discussed earlier.

Proxy Pattern

Motivation

Sometimes we need the ability to control the access to an object. For example if we need to use only a few methods of some costly objects we'll initialize those objects when we need them entirely. Until that point we can use some light objects exposing the same interface as the heavy objects. These light objects are called proxies and they will instantiate those heavy objects when they are really need and by then we'll use some light objects instead.
This ability to control the access to an object can be required for a variety of reasons: controlling when a costly object needs to be instantiated and initialized, giving different access rights to an object, as well as providing a sophisticated means of accessing and referencing objects running in other processes, on other machines.
Consider for example an image viewer program. An image viewer program must be able to list and display high resolution photo objects that are in a folder, but how often do someone open a folder and view all the images inside. Sometimes you will be looking for a particular photo, sometimes you will only want to see an image name. The image viewer must be able to list all photo objects, but the photo objects must not be loaded into memory until they are required to be rendered.

Intent

·         The intent of this pattern is to provide a “Placeholder” for an object to control references to it.

Implementation

The figure below shows a UML class diagram for the Proxy Pattern:
Proxy Pattern Implementation - UML Class Diagram
The participants classes in the proxy pattern are:

·         Subject - Interface implemented by the RealSubject and representing its services. The interface must be implemented by the proxy as well so that the proxy can be used in any location where the RealSubject can be used.

·         Proxy
o    Maintains a reference that allows the Proxy to access the RealSubject.
o    Implements the same interface implemented by the RealSubject so that the Proxy can be substituted for the RealSubject.
o    Controls access to the RealSubject and may be responsible for its creation and deletion.
o    Other responsibilities depend on the kind of proxy.

·         RealSubject - the real object that the proxy represents.

Description

A client obtains a reference to a Proxy, the client then handles the proxy in the same way it handles RealSubject and thus invoking the method doSomething(). At that point the proxy can do different things prior to invoking RealSubject’s doSomething() method. The client might create a RealSubject object at that point, perform initialization, check permissions of the client to invoke the method, and then invoke the method on the object. The client can also do additional tasks after invoking the doSomething() method, such as incrementing the number of references to the object.

Applicability & Examples

The Proxy design pattern is applicable when there is a need to control access to an Object, as well as when there is a need for a sophisticated reference to an Object. Common Situations where the proxy pattern is applicable are:

·         Virtual Proxies: delaying the creation and initialization of expensive objects until needed, where the objects are created on demand (For example creating the RealSubject object only when the doSomething method is invoked).

·         Remote Proxies: providing a local representation for an object that is in a different address space. A common example is Java RMI stub objects. The stub object acts as a proxy where invoking methods on the stub would cause the stub to communicate and invoke methods on a remote object (called skeleton) found on a different machine.

·         Protection Proxies: where a proxy controls access to RealSubject methods, by giving access to some objects while denying access to others.

·         Smart References: providing a sophisticated access to certain objects such as tracking the number of references to an object and denying access if a certain number is reached, as well as loading an object from database into memory on demand.

Example - Virtual Proxy Example.

Consider an image viewer program that lists and displays high resolution photos. The program has to show a list of all photos however it does not need to display the actual photo until the user selects an image item from a list.
Proxy Pattern Virtual Proxy Example - UML Class Diagram
The code below shows the Image interface representing the Subject. The interface has a single method showImage() that the Concrete Images must implement to render an image to screen.
package proxy;
 
/**
 * Subject Interface
 */
public interface Image {
 
        public void showImage();
        
}
The code below shows the Proxy implementation, the image proxy is a virtual proxy that creates and loads the actual image object on demand, thus saving the cost of loading an image into memory until it needs to be rendered:
package proxy;
 
/**
 * Proxy
 */
public class ImageProxy implements Image {
 
        /**
         * Private Proxy data 
         */
        private String imageFilePath;
        
        /**
         * Reference to RealSubject
         */
        private Image proxifiedImage;
        
        
        public ImageProxy(String imageFilePath) {
               this.imageFilePath= imageFilePath;    
        }
        
        @Override
        public void showImage() {
 
               // create the Image Object only when the image is required to be shown
               
               proxifiedImage = new HighResolutionImage(imageFilePath);
               
               // now call showImage on realSubject
               proxifiedImage.showImage();
               
        }
 
}

The code below displays the RealSubject Implementation, which is the concrete and heavyweight implementation of the image interface. The High resolution image, loads a high resolution image from disk, and renders it to screen when showImage() is called.
package proxy;
 
/**
 * RealSubject
 */
public class HighResolutionImage implements Image {
 
        public HighResolutionImage(String imageFilePath) {
               
               loadImage(imageFilePath);
        }
 
        private void loadImage(String imageFilePath) {
 
               // load Image from disk into memory
               // this is heavy and costly operation
        }
 
        @Override
        public void showImage() {
 
               // Actual Image rendering logic
 
        }
 
}

The code below illustrates a sample image viewer program; the program simply loads three images, and renders only one image, once using the proxy pattern, and another time directly. Note that when using the proxy pattern, although three images have been loaded, the High resolution image is not loaded into memory until it needs to be rendered, while in the part not using the proxy, the three images are loaded into memory although one of them is actually rendered.
package proxy;
 
/**
 * Image Viewer program
 */
public class ImageViewer {
 
        
        public static void main(String[] args) {
               
        // assuming that the user selects a folder that has 3 images 
        //create the 3 images  
        Image highResolutionImage1 = new ImageProxy("sample/veryHighResPhoto1.jpeg");
        Image highResolutionImage2 = new ImageProxy("sample/veryHighResPhoto2.jpeg");
        Image highResolutionImage3 = new ImageProxy("sample/veryHighResPhoto3.jpeg");
        
        // assume that the user clicks on Image one item in a list
        // this would cause the program to call showImage() for that image only
        // note that in this case only image one was loaded into memory
        highResolutionImage1.showImage();
        
        // consider using the high resolution image object directly
        Image highResolutionImageNoProxy1 = new HighResolutionImage("sample/veryHighResPhoto1.jpeg");
        Image highResolutionImageNoProxy2 = new HighResolutionImage("sample/veryHighResPhoto2.jpeg");
        Image highResolutionImageBoProxy3 = new HighResolutionImage("sample/veryHighResPhoto3.jpeg");
        
        
        // assume that the user selects image two item from images list
        highResolutionImageNoProxy2.showImage();
        
        // note that in this case all images have been loaded into memory 
        // and not all have been actually displayed
        // this is a waste of memory resources
        
        }
               
}

Specific problems and implementation

Java Remote Method Invocation (RMI)

In java RMI an object on one machine (executing in one JVM) called a client can invoke methods on an object in another machine (another JVM) the second object is called a remote object. The proxy (also called a stub) resides on the client machine and the client invokes the proxy in as if it is invoking the object itself (remember that the proxy implements the same interface that RealSubject implements). The proxy itself will handle communication to the remote object, invoke the method on that remote object, and would return the result if any to the client. The proxy in this case is a Remote proxy.

Related Patterns

·         Adapter Design Pattern - The adapter implements a different interface to the object it adapts where a proxy implements the same interface as its subject.

·         Decorator Design Pattern - A decorator implementation can be the same as the proxy however a decorator adds responsibilities to an object while a proxy controls access to it.

Consequences

Known Uses:
·         Java RMI as has been explained implements a remote proxy
·         Security Proxies that controls access to objects can be found in many object oriented languages including java, C#, C++.
This page is supported by web hosting search, a place you can use to find the best java hosting solutions.
 
Design Pattern Books
O'Reilly HeadFirst - Object Oriented Analysis and Design
O'Reilly HeadFirst Design Patterns

No comments: