定义
桥接模式即将抽象部分与实现部分脱耦,使它们可以独立变化。桥接模式的目的就是使两者分离,根据面向对象的封装变化的原则,我们可以把实现部分的变化封装到另外一个类中,这样的一个思路也就是桥接模式的实现。
- Abstraction----抽象化角色
它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般为抽象类。
- Implementor----实现化角色
它是接口或者抽象类,定义角色必需的行为和属性。
- RefindedAbstraction----修正抽象化角色
它引用实现化角色对抽象化角色进行修正。
- ConereteImplementor----具体实现化角色
它实现接口或者抽象类定义的方法和属性。
桥接模式实现
桥接模式的代码:
namespace ConsoleApplication1 { /// <summary> /// 实现化角色(待实现的接口) /// </summary> public interface Implementor { //基本方法 void doSomething(); void doAnything(); } /// <summary> /// 具体实现化角色 /// </summary> public class ConcreteImplementor1 : Implementor { public void doSomething() { //业务逻辑处理 } public void doAnything() { //业务逻辑处理 } } /// <summary> /// 具体实现化角色 /// </summary> public class ConcreteImplementor2 : Implementor { public void doSomething() { //业务逻辑处理 } public void doAnything() { //业务逻辑处理 } } /// <summary> /// 抽象化角色(调用者抽象) /// </summary> public abstract class Abstraction { //定义对实现化角色的引用 private Implementor imp; //获得实现化角色 public Implementor Imp { get { return imp; } } //约束为子类必须实现该构造函数 public Abstraction(Implementor _imp) { this.imp = _imp; } //自身的行为和属性 public virtual void request() { this.imp.doSomething(); } } /// <summary> /// 具体抽象化角色 /// </summary> public class RefindAbstraction : Abstraction { public RefindAbstraction(Implementor _imp) : base(_imp) { } //重载父类的方法 public override void request() { //业务处理 base.request(); base.Imp.doAnything(); } } class Program { static void Main(string[] args) { //定义一个实现化角色 Implementor imp = new ConcreteImplementor1(); //定义一个抽象化角色 Abstraction abs = new RefindAbstraction(imp); //执行行文 abs.request(); Console.ReadLine(); } } }
桥接模式的优缺点
介绍完桥接模式,让我们看看桥接模式具体哪些优缺点。
优点:
把抽象接口与其实现解耦。
抽象和实现可以独立扩展,不会影响到对方。
实现细节对客户透明,对用于隐藏了具体实现细节。
缺点: 增加了系统的复杂度
使用场景
我们再来看看桥接模式的使用场景,在以下情况下应当使用桥接模式:
- 如果一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联系。
- 设计要求实现化角色的任何改变不应当影响客户端,或者实现化角色的改变对客户端是完全透明的。
- 需要跨越多个平台的图形和窗口系统上。
- 一个类存在两个独立变化的维度,且两个维度都需要进行扩展。
一个实际应用桥接模式的例子
桥接模式也经常用于具体的系统开发中,对于三层架构中就应用了桥接模式,三层架构中的业务逻辑层BLL中通过桥接模式与数据操作层解耦(DAL),其实现方式就是在BLL层中引用了DAL层中一个引用。这样数据操作的实现可以在不改变客户端代码的情况下动态进行更换,下面看一个简单的示例代码:
namespace TempApplication { // 客户端调用 // 类似Web应用程序 class Client { static void Main(string[] args) { BusinessObject customers = new CustomersBusinessObject("ShangHai"); customers.Dataacces = new CustomersDataAccess(); customers.Add("小六"); Console.WriteLine("增加了一位成员的结果:"); customers.ShowAll(); customers.Delete("王五"); Console.WriteLine("删除了一位成员的结果:"); customers.ShowAll(); Console.WriteLine("更新了一位成员的结果:"); customers.Update("Learning_Hard"); customers.ShowAll(); Console.Read(); } } // BLL 层 public abstract class BusinessObject { // 字段 private DataAccess dataacess; private string city; public BusinessObject(string city) { this.city = city; } // 属性 public DataAccess Dataacces { get { return dataacess; } set { dataacess = value; } } // 方法 public virtual void Add(string name) { Dataacces.AddRecord(name); } public virtual void Delete(string name) { Dataacces.DeleteRecord(name); } public virtual void Update(string name) { Dataacces.UpdateRecord(name); } public virtual string Get(int index) { return Dataacces.GetRecord(index); } public virtual void ShowAll() { Console.WriteLine(); Console.WriteLine("{0}的顾客有:", city); Dataacces.ShowAllRecords(); } } public class CustomersBusinessObject : BusinessObject { public CustomersBusinessObject(string city) : base(city) { } // 重写方法 public override void ShowAll() { Console.WriteLine("------------------------"); base.ShowAll(); Console.WriteLine("------------------------"); } } ///<summary> /// 相当于三层架构中数据访问层(DAL) ///</summary> public abstract class DataAccess { // 对记录的增删改查操作 public abstract void AddRecord(string name); public abstract void DeleteRecord(string name); public abstract void UpdateRecord(string name); public abstract string GetRecord(int index); public abstract void ShowAllRecords(); } public class CustomersDataAccess:DataAccess { // 字段 private List<string> customers =new List<string>(); public CustomersDataAccess() { // 实际业务中从数据库中读取数据再填充列表 customers.Add("Learning Hard"); customers.Add("张三"); customers.Add("李四"); customers.Add("王五"); } // 重写方法 public override void AddRecord(string name) { customers.Add(name); } public override void DeleteRecord(string name) { customers.Remove(name); } public override void UpdateRecord(string updatename) { customers[0] = updatename; } public override string GetRecord(int index) { return customers[index]; } public override void ShowAllRecords() { foreach (string name in customers) { Console.WriteLine("" + name); } } } }