参考:head first 设计模式
参考:https://www.cnblogs.com/zhili/p/BridgePattern.html
应用场景
先来个例子: 电视遥控器:
每个牌子的电视机都有一个遥控器,将遥控器的功能作为一个抽象类,
抽象类中提供遥控器的功能实现,有三星长虹等品牌的遥控器,可以继承此类。后期也可以再加入tcl等品牌,但是随着时间的推移,用户需要改变遥控器的功能,如:添加返回上一个台的按键。
这时需要修改抽象类中的接口(添加一个方法),但是我们改变了抽象的实现。要同时改变电视机型号和遥控器功能时,上面的设计会导致大量的修改。
可以用桥接模式解决,Bridge中将抽象部分与实现部分解耦,使它们可以独立变化,桥接的目的是将抽象类和继承类分离。
桥接模式实现了抽象化与实现化的解耦,使它们独立互不影响到对方。
如果一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联络。
设计要求实现化角色的任何改变不应当影响客户端,或者抽象化角色的改变对客户端是完全透明的。
需要跨越多个平台的图形和窗口系统上。
一个类存在两个独立变化的维度,且两个维度都需要进行扩展。
结构
桥接角色:RemoteControl 包含对抽象化角色的引用
具体实现角色:ConcreteRemote 设置引用的相关信息
抽象化角色:TV 要实现的各种模块
桥接抽象类的具体实现:ConcreteTV (ChangHong SanXing)
图例
特点
优点:
把抽象类和实现解耦,抽象和实现可以独立扩展,不会影响到对方。实现了细节对客户透明,对用户隐藏了具体实现细节。
缺点:
增加系统复杂度
实际 例子
三层架构: 业务逻辑中(BLL)通过桥接模式与数据操作层解耦(DAL),其实现方式就是在BLL层中引用了DAL层中的一个引用,这样数据操作的实现可以在不改变客户端代码的情况下动态进行更换
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DesignPattern
{
public class BridgeClient
{
public static void main()
{
//创建遥控器
RemoteControl ctl = new ConcreteRemote();
//changhong
ctl.Implementor = new ChangHongTV();
ctl.On();
ctl.SetChannel();
ctl.Off();
//sanxing
ctl.Implementor = new SanXingTV();
ctl.On();
ctl.SetChannel();
ctl.Off();
//桥接模式中 遥控器的功能实现部分不在遥控器抽象类中实现了,而是把实现部分
//封装到另一个电视机类中,然后遥控器中只包含电视机类的一个引用
//例子
BusinessObject bo = new CustomerBusinessObject("shanghai");
bo.Dataaccess = new CustomersDataAccess();
bo.Add("xiao liu");
bo.ShowAll();
bo.Add("xiao");
bo.ShowAll();
bo.Delete("xiao");
bo.ShowAll();
bo.Update("xyz");
bo.ShowAll();
}
}
/// <summary>
/// 抽象概念中的遥控器,扮演抽象化角色
/// </summary>
public class RemoteControl
{
/// <summary>
/// 桥接点
/// </summary>
private TV implementor;
public TV Implementor
{
get { return implementor; }
set { implementor = value; }
}
/// <summary>
/// 抽象类不中再提供实现,而是调用实现类中的实现
/// </summary>
public virtual void On()
{
implementor.On();
}
public virtual void Off()
{
implementor.Off();
}
public virtual void SetChannel()
{
implementor.SetChannel();
}
}
/// <summary>
/// 具体遥控器
/// </summary>
public class ConcreteRemote : RemoteControl
{
public override void SetChannel()
{
Console.WriteLine(typeof(ConcreteRemote).FullName);
base.SetChannel();
}
}
/// <summary>
/// 实现部分代码,用另外一个抽象类TV封装了遥控器功能的变化
/// 具体实现交给具体型号机器去完成 电视机提供抽象方法
/// </summary>
public abstract class TV
{
public abstract void On();
public abstract void Off();
public abstract void SetChannel();
}
/// <summary>
/// 桥接抽象类的具体实现
/// </summary>
public class ChangHongTV : TV
{
public override void On()
{
Console.WriteLine(nameof(ChangHongTV) + "On");
}
public override void Off()
{
Console.WriteLine(nameof(ChangHongTV) + "Off");
}
public override void SetChannel()
{
Console.WriteLine("Change channel");
}
}
/// <summary>
/// 桥接抽象类的具体实现
/// </summary>
public class SanXingTV : TV
{
public override void On()
{
Console.WriteLine(nameof(SanXingTV) + "On");
}
public override void Off()
{
Console.WriteLine(nameof(SanXingTV) + "Off");
}
public override void SetChannel()
{
Console.WriteLine(nameof(SanXingTV) + "SetChannel");
}
}
/// <summary>
/// 实际例子 三层模式
/// </summary>
public class BusinessObject
{
private DataAccess dataAccess;
private string city;
public BusinessObject(string city)
{
this.city = city;
}
public DataAccess Dataaccess
{
get { return dataAccess; }
set { dataAccess = value; }
}
public virtual void Add(string name)
{
Dataaccess.AddRecord(name);
}
public virtual void Delete(string name)
{
Dataaccess.DeleteRecord(name);
}
public virtual void Update(string name)
{
Dataaccess.UpdateRecord(name);
}
public virtual string Get(int index)
{
return Dataaccess.GetRecord(index);
}
public virtual void ShowAll()
{
Dataaccess.ShowAllRecords();
}
}
public class CustomerBusinessObject : BusinessObject
{
public CustomerBusinessObject(string city) : base(city)
{ }
public override void ShowAll()
{
base.ShowAll();
}
}
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 IList<string> customers = new List<string>();
public CustomersDataAccess()
{
customers.Add("A1");
customers.Add("A2");
customers.Add("A3");
customers.Add("A4");
}
// 重写方法
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);
}
}
}
}