Open main menu

CDOT Wiki β

Changes

Bridge

8,725 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/PatternBridge.aspx
<br/>
<br/>
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.jpg]]<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>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:<br />
<ul>
<li>'''Abstraction'''</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>
<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>
== Collaborations ==
== Consequences ==
The Bridge pattern has the following consequence:
<ul>
<li>Decoupling interface and implementation</li>
<li>Improved extensibility</li>
<li>Hiding implementation detail from clients</li>
</ul>
== Implementation 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"   class Customers : CustomersBase { // Constructor public Customers(string group) : base(group) { }  public override void ShowAll() { // Add separator lines Console.WriteLine(); Console.WriteLine ("------------------------"); base.ShowAll(); Console.WriteLine ("------------------------"); } }  // "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 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 = Code Examples 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