类图:
抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。
修正抽象化(RefinedAbstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
具体实现化(ConcreteImplementor)角色:这个角色给出实现化角色接口的具体实现。
咖啡的例子
原文见:https://zhuanlan.zhihu.com/p/58903776
类图:
这里勇哥给出C#的演示代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 桥接模式_点咖啡2 { /* 项目经理突然过来了:蛋大啊,客户那边说了, 他们准备加两个容量规格的咖啡,大杯和小杯,你改一下。 加着加着蛋大慌了,共需要3x2=6个类啊,大杯原味和加糖,中杯原味和加糖,小杯原味和加糖。 过段时间万一那二笔客户又要出加奶,加蜂蜜等等口味, 说不定还有迷你杯,女神杯等等规格的咖啡, 那我这边的类不就爆炸了吗?看来的去找个设计模式了。。。 此场景桥接模式正合适,这里有两个变化维度,咖啡的容量和口味, 而且都需要独立变化。如果使用继承的方式,随着变化类就会急剧的增加。 你可以将容量理解为抽象部分,而口味理解为实现部分,这两个部分需要桥接。 */ class Program { static void Main(string[] args) { RefinedAbstraction db = new 大杯牛奶(new 加奶()); db.orderCoffee(2); db.checkQuality(); Console.ReadKey(); } } /// <summary> /// 抽象化(Abstraction)角色 /// </summary> public abstract class Abstraction { protected abstract Implementor 口味 { get; set; } public Abstraction(Implementor _口味) { this.口味 = _口味; } public abstract void orderCoffee(int count); } /// <summary> /// 修正抽象化(RefinedAbstraction)角色 /// </summary> public abstract class RefinedAbstraction : Abstraction { protected override Implementor 口味 { get; set; } public RefinedAbstraction(Implementor _口味) : base(_口味) { 口味 = _口味; } public void checkQuality() { Console.WriteLine($"{口味.GetType().Name},正常"); } } public class 大杯牛奶 : RefinedAbstraction { protected override Implementor 口味 { get; set; } public 大杯牛奶(Implementor add) : base(add) { 口味 = add; } public override void orderCoffee(int count) { 口味.addSomething(); Console.WriteLine($"大杯咖啡{count}杯"); } } /// <summary> /// 实现化(Implementor)角色 /// </summary> public interface Implementor { void addSomething(); } /// <summary> /// 具体实现化(ConcreteImplementor)角色1 /// </summary> public class 加奶 : Implementor { public void addSomething() { Console.WriteLine($"加奶"); } } /// <summary> /// 具体实现化(ConcreteImplementor)角色2 /// </summary> public class 加糖 : Implementor { public void addSomething() { Console.WriteLine($"加糖"); } } }
这篇文章有位读者的点评很能说明桥接模式的特点:将m*n个实现类转换为m+n个实现类
图片在不同系统下显示
原文链接:
https://www.jianshu.com/p/516a6beb42c3
代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { class Program { static void Main(string[] args) { WindowsSystem win = new WindowsSystem(); LinuxSystem lin = new LinuxSystem(); Image jpgSys = new JPGImage(system: win, format: "jpg"); jpgSys.ParseFile(); Image jpgLin = new JPGImage(system: lin, format: "jpg"); jpgLin.ParseFile(); Image pngSys = new PNGImage(system: win, format: "png"); pngSys.ParseFile(); Image pngLin = new PNGImage(system: lin, format: "png"); pngLin.ParseFile(); Console.ReadKey(); } } public abstract class Image { public System System { get; protected set; } public string Format { get; protected set; } public Image(System system, string format) { System = system; Format = format; } public void ParseFile() { System.Show(Format); } } public class JPGImage : Image { public JPGImage(System system, string format) : base(system, format) { } } public class PNGImage : Image { public PNGImage(System system, string format) : base(system, format) { } } public abstract class System { public virtual void Show(string format) { // 基础实现,可以在子类中被覆盖 } } public class WindowsSystem : System { public override void Show(string format) { Console.WriteLine($"{format}格式在Windows系统下显示"); } } public class LinuxSystem : System { public override void Show(string format) { Console.WriteLine($"{format}格式在Linux系统下显示"); } } }
结果:
需求V2:增加新的图像文件格式TIF
只需要创建TIFImage继承自Image即可
public class TIFImage : Image { //public TIFImage(System system, string format) : base(system, format) { } } TIFImage tifSys = new TIFImage(system: win, format: "tif"); tifSys.ParseFile(); TIFImage tifLin = new TIFImage(system: lin, format: "tif"); tifLin.ParseFile();
需求V3:增加一个新的操作系统Mac OS
只需要创建MacOSSystem继承自System即可
public class MacOSSystem : System { public override void Show(string format) { Console.WriteLine($"{format}格式在Mac OS系统下显示"); } } //客户端: MacOSSystem mac = new MacOSSystem(); Image jpgMac = new JPGImage(system: mac, format: "jpg"); jpgMac.ParseFile(); Image pngMac = new PNGImage(system: mac, format: "png"); pngMac.ParseFile(); Image tifMac = new TIFImage(system: mac, format: "tif"); // 注意这里应该是TIFImage而不是JPGImage tifMac.ParseFile();
另一篇:
https://zhuanlan.zhihu.com/p/666037755
https://baijiahao.baidu.com/s?id=1736389582955994797&wfr=spider&for=pc

