 |
Decouple an abstraction from its implementation so that the two can vary
independently.
Frequency of use: nbsp;medium
|
|
 |
The classes and/or objects participating in this pattern are:
- Abstraction (BusinessObject)
- defines the abstraction's interface.
- maintains a reference to an object of type Implementor.
- RefinedAbstraction (CustomersBusinessObject)
- extends the interface defined by Abstraction.
- Implementor (DataObject)
- defines the interface for implementation classes. This interface doesn't
have to correspond exactly to Abstraction's interface; in fact the two interfaces
can be quite different. Typically the Implementation interface provides only
primitive operations, and Abstraction defines higher-level operations based on
these primitives.
- ConcreteImplementor (CustomersDataObject)
- implements the Implementor interface
and defines its concrete implementation.
This structural code demonstrates the Bridge pattern which separates (decouples) the interface from
its implementation. The implementation can evolve without changing clients
which use the abstraction of the object.
Show code
|
// Bridge pattern -- Structural example
|
|
using System;
namespace DoFactory.GangOfFour.Bridge.Structural
{
// MainApp test application
class MainApp
{
static void Main()
{
Abstraction ab = new RefinedAbstraction();
// Set implementation and call
ab.Implementor = new ConcreteImplementorA();
ab.Operation();
// Change implemention and call
ab.Implementor = new ConcreteImplementorB();
ab.Operation();
// Wait for user
Console.Read();
}
}
// "Abstraction"
class Abstraction
{
protected Implementor implementor;
// Property
public Implementor Implementor
{
set{ implementor = value; }
}
public virtual void Operation()
{
implementor.Operation();
}
}
// "Implementor"
abstract class Implementor
{
public abstract void Operation();
}
// "RefinedAbstraction"
class RefinedAbstraction : Abstraction
{
public override void Operation()
{
implementor.Operation();
}
}
// "ConcreteImplementorA"
class ConcreteImplementorA : Implementor
{
public override void Operation()
{
Console.WriteLine("ConcreteImplementorA Operation");
}
}
// "ConcreteImplementorB"
class ConcreteImplementorB : Implementor
{
public override void Operation()
{
Console.WriteLine("ConcreteImplementorB Operation");
}
}
}
|
Output
ConcreteImplementorA Operation
ConcreteImplementorB Operation
|
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.
Show code
|
// 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);
}
}
}
}
|
Output
Jim Jones
Samual Jackson
Allen Good
------------------------
Customer Group: Chicago
Jim Jones
Samual Jackson
Allen Good
Ann Stills
Lisa Giolani
Henry Velasquez
------------------------
|
This .NET optimized code demonstrates the
same real-world situation as above but uses modern, built-in .NET features.
Show code
|
// Bridge pattern -- .NET optimized
|
See our Singleton page for a .NET optimized code sample.
|
|
|