Open main menu

CDOT Wiki β

Changes

Bridge

10,203 bytes added, 09:52, 11 June 2007
Consequences
The '''Bridge pattern''' allows you to decouple an abstraction from its implementation so both can vary independently. The Bridge pattern is also know as Handle/Body.<br/><br/>
 
__TOC__
== Introduction ==
The '''bridge pattern''' is a design pattern used in software developing, decouple an abstraction from its implementation so that the two can vary independently. It is also known as Handle or Body.
== UML Structure ==
Here is an example of the Bridge pattern.<br/>[[Image:Bridge.gif]]<br/>Source: Downloaded from http://www.dofactory.com/Patterns/DiagramsPatternBridge.aspx<br/><br/bridge>Here is another example of the Bridge pattern where it decouples the abstraction from its implementation so that the two can vary independently[[Image:Gof7.gifjpg]]<br/>Source: Downloaded from http://home.earthlink.net/~huston2/dp/all_uml.html<br/>
== Applicability ==
The Bridge pattern is applicable when:
<ul><ul>
<li>we want to avoid a permanent binding between an abstraction and its implementation</li>
<li>both the abstractions and their implementations should be extensible by subclassing</li>
<li>changes in the implementation of an abstraction should have no impact on clients</li>
<li>we want to hide the implementation of an abstraction completely from clients</li>
<li>we want to share an implementation among multiple objects, and this fact should be hiddent from the client</li>
<li>useful in graphic and windowing systems that need to run over multiple platforms</li>
<li>useful any time we need to vary an interface and an implementation in different ways</li>
</ul></ul>
== Participants ==
The classes and/or objects participating in this pattern are:
<ul>
<li>'''Abstraction'''</li>
<ul>
<li>defines the abstraction's interface</li>
<li>maintains a reference to an object of type Implementor</li>
</ul>
<li>'''Refined Abstraction'''</li>
<ul>
<li>extends the interface defined by Abstraction.</li>
</ul>
<li>'''Implementor'''</li>
<ul>
<li>defines the interface for implementation classes. This interface does not have to correspond exactly to Abstraction's interface; in fact the two interfaces can be quite different. The Implementation interface provides only primitive operations, and Abstraction defines high-level operations based on these primitives.</li>
</ul>
<li>'''Concrete Implementor'''</li>
<ul>
<li>implements the Implementor interface and defines its concrete implementation.</li>
</ul>
</ul>
 
 
 
== Code Examples ==
 
====PHP Java Bridge in Java Code====
The following code is found on "Oregon State University Open Source Lab" which illustrate the Bridge pattern. The following is a part of the code which allows user to vary the class loader. <br/>
Source: http://gentoo.osuosl.org/distfiles/php-java-bridge_2.0.8.tar.bz2<br/>
File: JavaBridge.java<br/>
<pre>
package php.java.bridge;
 
 
/**
* A bridge pattern which allows us to vary the class loader as run-time.
* The decision is based on whether we are allowed to use a dynamic
* classloader or not (loader==null).
* @see DynamicJavaBridgeClassLoader
* @see java.lang.ClassLoader
*/
public class JavaBridgeClassLoader {
 
DynamicJavaBridgeClassLoader cl = null;
ClassLoader scl = null;
private JavaBridge bridge;
 
public JavaBridgeClassLoader(JavaBridge bridge, DynamicJavaBridgeClassLoader loader) {
this.bridge = bridge;
this.cl = loader;
 
if(this.cl==null)
this.scl = bridge.getClass().getClassLoader();
else
cl.clear();
}
 
/**
* Append the path to the current library path
* @param path A file or url list, separated by ';'
* @param extensionDir Usually ini_get("extension_dir");
*/
public void updateJarLibraryPath(String path, String extensionDir) {
if(cl==null) {
bridge.logMessage("You don't have permission to call java_set_library_path()
or java_require(). Please store your libraries in the lib
folder within JavaBridge.war");
return;
}
 
cl.updateJarLibraryPath(path, extensionDir);
}
 
/**
* Only for internal use
* @return the classloader
*/
public ClassLoader getClassLoader() {
if(cl!=null) return (ClassLoader)cl;
return scl;
}
 
/**
* reset loader to the initial state
*/
public void reset() {
if (cl!=null) cl.reset();
}
 
/**
* clear all loader caches but
* not the input vectors
*/
public void clearCaches() {
if (cl!=null) cl.clearCaches();
}
 
/**
* Load a class.
* @param name The class, for example java.lang.String
* @return the class
* @throws ClassNotFoundException
*/
public Class forName(String name) throws ClassNotFoundException {
if(cl==null) return Class.forName(name, false, scl);
return cl.loadClass(name);
}
 
}
</pre>
 
====Real-world Sample code in C#====
This real-world code demonstrates the Bridge pattern in which a BusinessObject abstraction is decoupled from the implementation in DataObject. The DataObject implementations can evolve dynamically without changing any clients. <br/>
Source: http://www.dofactory.com/Patterns/PatternBridge.aspx
<pre>
// Bridge pattern -- Real World example
 
using System;
using System.Collections;
 
namespace DoFactory.GangOfFour.Bridge.RealWorld
{
 
// MainApp test application
class MainApp
{
static void Main()
{
// Create RefinedAbstraction
Customers customers =
new Customers("Chicago");
 
// Set ConcreteImplementor
customers.Data = new CustomersData();
 
// Exercise the bridge
customers.Show();
customers.Next();
customers.Show();
customers.Next();
customers.Show();
customers.New("Henry Velasquez");
 
customers.ShowAll();
 
// Wait for user
Console.Read();
}
}
 
// "Abstraction"
 
class CustomersBase
{
private DataObject dataObject;
protected string group;
 
public CustomersBase(string group)
{
this.group = group;
}
 
// Property
public DataObject Data
{
set{ dataObject = value; }
get{ return dataObject; }
}
 
public virtual void Next()
{
dataObject.NextRecord();
}
 
public virtual void Prior()
{
dataObject.PriorRecord();
}
 
public virtual void New(string name)
{
dataObject.NewRecord(name);
}
 
public virtual void Delete(string name)
{
dataObject.DeleteRecord(name);
}
 
public virtual void Show()
{
dataObject.ShowRecord();
}
 
public virtual void ShowAll()
{
Console.WriteLine("Customer Group: " + group);
dataObject.ShowAllRecords();
}
}
 
// "RefinedAbstraction"
== Collaborations == class Customers : CustomersBase { // Constructor public Customers(string group) : base(group) { }
== Consequences == public override void ShowAll() { // Add separator lines Console.WriteLine(); Console.WriteLine ("------------------------"); base.ShowAll(); Console.WriteLine ("------------------------"); } }
== Implementation == // "Implementor"
abstract class DataObject { public abstract void NextRecord(); public abstract void PriorRecord(); public abstract void NewRecord(string name); public abstract void DeleteRecord(string name); public abstract void ShowRecord(); public abstract void ShowAllRecords(); }  // "ConcreteImplementor"   class CustomersData : DataObject { private ArrayList customers =new ArrayList(); private int current = 0;  public CustomersData() { // Loaded from a database customers.Add("Jim Jones"); customers.Add("Samual Jackson"); customers.Add("Allen Good"); customers.Add("Ann Stills"); customers.Add("Lisa Giolani"); }  public override void NextRecord() { if (current <= customers.Count - 1) { current++; } }  public override void PriorRecord() { if (current > 0) { current--; } }  public override void NewRecord(string name) { customers.Add(name); }  public override void DeleteRecord(string name) { customers.Remove(name); }  public override void ShowRecord() { Console.WriteLine(customers[current]); }  public override void ShowAllRecords() { foreach (string name in customers) { Console.WriteLine(" " + name); } } }} </pre> ====Sample Code Examples in Java====The following is an easier to follow example of the Bridge pattern:<br/>Source: http://en.wikipedia.org/wiki/Bridge_pattern<pre>import java.util.*;/** "Implementor" */interface DrawingAPI { public void drawCircle(double x, double y, double radius);} /** "ConcreteImplementor" 1/2 */class DrawingAPI1 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius); }} /** "ConcreteImplementor" 2/2 */class DrawingAPI2 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius); }} /** "Abstraction" */interface Shape { public void draw(); // low-level public void resizeByPercentage(double pct); // high-level} /** "Refined Abstraction" */class CircleShape implements Shape { private double x, y, radius; private DrawingAPI drawingAPI; public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) { this.x = x; this.y = y; this.radius =radius; this.drawingAPI =drawingAPI; }
// low-level i.e. Implementation specific public void draw() { drawingAPI.drawCircle(x, y, radius); } // high-level i.e. Abstraction specific public void resizeByPercentage(double pct) { radius *== Related Patterns ==Abstract Factory pct; }Adapter}
/** "Client" */class BridgePattern { public static void main(String[] args) { Shape[] shapes =new Shape[2]; shapes[0] = References =new CircleShape(1, 2, 3, new DrawingAPI1()); shapes[1] =new CircleShape(5, 7, 11, new DrawingAPI2());
for (Shape shape : shapes) {
shape.resizeByPercentage(2.5);
shape.draw();
}
}
}
</pre>
== Other References ==<ul><li>[http://en.wikipedia.org/wiki/Bridge_pattern Wikipedia.com - Bridge pattern]</li><li>[http://www.developer.com/design/article.php/1502691 A Survey of Common Design Patterns]</li><li>[http://www.dofactory.com/Patterns/PatternBridge.aspx DoFactory.com - Bridge Design Pattern]</li><li>[http://home.earthlink.net/~huston2/dp/all_uml.html Design Class Diagrams - Bridge]</li><li>[http://gentoo.osuosl.org/distfiles/php-java-bridge_2.0.8.tar.bz2 Oregon State University Open Source Lab - JavaBridge.java]</li><li>Gamma, E., Helm, R., Johnson, R., Vlissides, J. (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. ISBN 0-201-63361-2 </li></ul>
1
edit