存在目地:将抽象部分与实现部分分离,使它们都可以独立的变化。也即将抽象和实现进行脱耦,使用组合/聚合关系而不是继承使二者可以相对独立的变化。
应用场合:某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。
实现方式:
using System;
// 抽象化角色,抽象化给出的定义,并保存一个对实现化对象的引用
class Abstraction
{
// 实现化对象implementor
protected Implementor implementor;
// Properties
public Implementor Implementor
{
set{ implementor = value; }
}
// Methods
virtual public void Operation()
{
implementor.Operation();
}
}
// 修正抽象化角色,扩展抽象化角色,改变和修正父类对抽象化的定义
class RefinedAbstractionA : Abstraction
{
// Methods
override public void Operation()
{
implementor.Operation();
}
}
class RefinedAbstractionB : Abstraction
{
// Methods
override public void Operation()
{
implementor.Operation();
}
}
// 实现化角色,给出具体实现化角色的接口
abstract class Implementor
{
// Methods
abstract public void Operation();
}
// 具体实现化角色,给出实现化角色接口的具体实现
class ConcreteImplementorA : Implementor
{
// Methods
override public void Operation()
{
Console.WriteLine("ConcreteImplementorA Operation");
}
}
class ConcreteImplementorB : Implementor
{
// Methods
override public void Operation()
{
Console.WriteLine("ConcreteImplementorB Operation");
}
}
/** <summary>
/// Client test
/// </summary>
public class Client
{
public static void Main( string[] args )
{
Abstraction abstraction = new RefinedAbstractionA();
// Set implementation and call
abstraction.Implementor = new ConcreteImplementorA();
abstraction.Operation();
// Change implemention and call
abstraction.Implementor = new ConcreteImplementorB();
abstraction.Operation();
abstraction = new RefinedAbstractionB();
// Set implementation and call
abstraction.Implementor = new ConcreteImplementorA();
abstraction.Operation();
// Change implemention and call
abstraction.Implementor = new ConcreteImplementorB();
abstraction.Operation();
}
}
另一个关于日志记录的代码实例,在两种不同的平台下.NET和Java两种记录方式
public abstract class ImpLog
{
public abstract void Execute(string msg);
}
public class NImpLog : ImpLog
{
public override void Execute(string msg)
{
//...... .NET平台
}
}
public class JImpLog : ImpLog
{
public override void Execute(string msg)
{
//...... Java平台
}
}
public abstract class Log
{
protected ImpLog implementor;
public ImpLog Implementor
{
set { implementor = value; }
}
public virtual void Write(string log)
{
implementor.Execute(log);
}
}
public class DatabaseLog : Log
{
public override void Write(string log)
{
implementor.Execute(log);
}
}
public class TextFileLog : Log
{
public override void Write(string log)
{
implementor.Execute(log);
}
}
class App
{
public static void Main(string[] args)
{
//.NET平台下的Database Log
Log dblog = new DatabaseLog();
dblog.Implementor = new NImpLog();
dblog.Write();
//Java平台下的Text File Log
Log txtlog = new TextFileLog();
txtlog.Implementor = new JImpLog();
txtlog.Write();
}
}
适用性:
如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系。
设计要求实现化角色的任何改变不应当影响客户端,或者说实现化角色的改变对客户端是完全透明的。
一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合。
虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。
参考资料:
Erich Gamma《设计模式可复用面向对象软件的基础》