设计模式之Bridge桥接设计模式

意图 intent :将抽象部分与它的实现部分分离,使它们都可以独立地变化。

适用性:

  • 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
  • c++)你想对客户完全隐藏抽象的实现部分。在c++中,类的表示在类接口中是可见的。
  • 有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。Rumbaugh称这种类层次结构为嵌套的普化nested generalizations)。
  • 你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。一个简单的例子便是CoplienString[Cop92],在这个类中多个对象可以共享同一个字符串表示(StringRep)。

定义definitionDecouple an abstraction from its implementation so that the two can vary independently. 分离抽象与其实现以使他们能够独立的变化。

Participants

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.

sample code in C#

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.

// 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.

// 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

------------------------

 

 

看着UML class diagram和上面的code,理解bridge不是很困难,不过好像也没多大感觉哦。说实在的,缺乏实际经验,不是很理解为什么要这么做。不过有一点是肯定的,那就是这个模式的好处就是抽象和实现都可以变化。Abstraction用有一个implementor的实例对象,然后基类这一层的是这样子的,Abstraction拥有一个函数operation,此函数体执行的是implementor的函数OperationImp。这样子的话,我们就可以通过继承implementor来获得concrete implementor,然后Abstractionoperation执行的就是concrete implmentorOperationImp了。此时,就是一个有点变形的Adapter模式了,不信的话你去看UML class diagram。这个时候,我们的Abstraction也要变化了!sigh,要变得东西真多啊,呵呵。所以我们又对Abstraction进行继承、泛化得到RefinedAbstraction。此时,我们不必改operation函数就可以保证我们这边的改变不会影响到implementor那一块的代码了。还是很不错的。恩。Over

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值