桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们均可以独立地变化。(实现系统可能有多角度分类,每一种分类都有可能变化(只用继承会形成类的大量增长,不能知足开放——封闭原则),那么就把这种多角度分离出来让它们独立变化,减小它们之间的耦合)java
抽象与它的实现分离,并非说让抽象类与其派生类分离,实现指的是抽象类和它的派生类用来实现本身的对象。例:手机既能够按照品牌来分类,也能够按照功能来分类,具体能够参考下面实例:c#
按品牌分类:ide
按软件实现分类:this
因为实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让他们各自地变化,这就使得每种实现的变化不会影响其余实现,从而达到应对变化的目的。code
桥接模式实现:对象
这样就解决了按品牌分类或按软件分类增长新品牌/软件时的复杂性和代码不可复用性。继承
桥接模式UML结构图:接口
例(手机软件):游戏
//手机品牌 abstract class HandsetBrand { protected HandsetSoft soft; //设置手机软件 public void SetHandsetSoft(HandsetSoft soft) { this.soft = soft; } //运行 public abstract void Run(); } //手机品牌N class HandsetBrandN : HandsetBrand { public override void Run() { soft.Run(); } } //手机品牌M class HandsetBrandM : HandsetBrand { public override void Run() { soft.Run(); } } //手机品牌S class HandsetBrandS : HandsetBrand { public override void Run() { soft.Run(); } } //手机软件 abstract class HandsetSoft { public abstract void Run(); } //手机游戏 class HandsetGame : HandsetSoft { public override void Run() { Console.WriteLine("运行手机游戏"); } } //手机通信录 class HandsetAddressList : HandsetSoft { public override void Run() { Console.WriteLine("运行手机通信录"); } } //手机MP3播放 class HandsetMP3 : HandsetSoft { public override void Run() { Console.WriteLine("运行手机MP3播放"); } } class Program { static void Main(string[] args) { HandsetBrand ab; ab = new HandsetBrandN(); ab.SetHandsetSoft(new HandsetGame()); ab.Run(); ab.SetHandsetSoft(new HandsetAddressList()); ab.Run(); ab = new HandsetBrandM(); ab.SetHandsetSoft(new HandsetGame()); ab.Run(); ab.SetHandsetSoft(new HandsetAddressList()); ab.Run(); Console.Read(); } }
例(发送提示消息):ci
消息分红普通消息、加急消息和特急消息多种,不一样的消息类型,业务功能处理是不同的,好比加急消息是在消息上添加加急,而特急消息除了添加特急外,还会作一条催促的记录,多久不完成会继续催促。从发送消息的手段上看,又有系统内短消息、手机短消息、邮件等等。
所有采用继承,不使用桥接模式的UML图(若是继续扩展消息类型或者发送方式将会十分繁琐):
例:继续添加发送手机消息的处理方式(这个时候代码结构就逐渐开始变得复杂):
桥接模式实现:
代码:
public interface MessageImplementor { public void send(String message,String toUser); } public class MessageEmail implements MessageImplementor { public void send(String message, String toUser) { System.out.println("使用Email的方式,发送消息'" + message + "'给" + toUser); } } public class MessageMobile implements MessageImplementor { public void send(String message, String toUser) { System.out.println("使用手机短消息的方式,发送消息'" + message + "'给" + toUser); } } public class MessageSMS implements MessageImplementor { public void send(String message, String toUser) { System.out.println("使用站内短消息的方式,发送消息'" + message + "'给" + toUser); } } public abstract class AbstractMessage { protected MessageImplementor impl; public AbstractMessage(MessageImplementor impl) { this.impl = impl; } public void sendMessage(String message, String toUser) { this.impl.send(message, toUser); } } public class CommonMessage extends AbstractMessage { public CommonMessage(MessageImplementor impl) { super(impl); } public void sendMessage(String message, String toUser) { super.sendMessage(message, toUser); } } public class UrgencyMessage extends AbstractMessage { public UrgencyMessage(MessageImplementor impl) { super(impl); } public void sendMessage(String message, String toUser) { message = "加急:" + message; super.sendMessage(message, toUser); } public Object watch(String messageId) { return null; } } public class SpecialUrgencyMessage extends AbstractMessage { public SpecialUrgencyMessage(MessageImplementor impl) { super(impl); } public void hurry(String messageId) { // 执行催促的业务,发出催促的信息 } public void sendMessage(String message, String toUser) { message = "特急:" + message; super.sendMessage(message, toUser); } } /* * 意图:将抽象部分与实现部分分离,使它们均可以独立的变化。 * 主要解决:在有多种可能会变化的状况下,用继承会形成类爆炸问题,扩展起来不灵活。 * 什么时候使用:实现系统可能有多个角度分类,每一种角度均可能变化。 * 如何解决:把这种多角度分类分离出来,让它们独立变化,减小它们之间耦合。 * 关键代码:抽象类依赖实现类。 */ /* * 该发送消息的实例因为发送方式的可扩展性和发送级别(普通,加急,特急等)的可扩展性,使用继承并不灵活 * 考虑使用桥接模式:分离这两部分,使它们独立变化,减小它们之间的耦合(低耦合) * 注意事项:有时候咱们看待问题的角度不一样,可能采起的分离措施也会有所不一样,所以代码结构也会有所不一样 *(这种过于复杂的状况下桥接模式就再也不能说很合适,由于桥接模式自己就加重了代码的复杂性,较于继承更加难以理解一些,可是使用得当则会让代码结构更加简洁清晰) */ public class Client { public static void main(String[] args) { MessageImplementor impl = new MessageSMS(); //接口下的发送方式定义 AbstractMessage m = new CommonMessage(impl); //发送消息的方式实现 m.sendMessage("请喝一杯茶", "小李"); m = new UrgencyMessage(impl); m.sendMessage("请喝一杯茶", "小李"); m = new SpecialUrgencyMessage(impl); m.sendMessage("请喝一杯茶", "小李"); impl = new MessageMobile(); m = new CommonMessage(impl); m.sendMessage("请喝一杯茶", "小李"); m = new UrgencyMessage(impl); m.sendMessage("请喝一杯茶", "小李"); m = new SpecialUrgencyMessage(impl); m.sendMessage("请喝一杯茶", "小李"); impl = new MessageEmail(); m = new CommonMessage(impl); m.sendMessage("请喝一杯茶", "小李"); m = new UrgencyMessage(impl); m.sendMessage("请喝一杯茶", "小李"); m = new SpecialUrgencyMessage(impl); m.sendMessage("请喝一杯茶", "小李"); } }