设计模式 之 桥接模式解析

    xiaoxiao2022-07-07  203

    预计阅读时间:10 分钟

    1、桥接模式的定义

    将抽象部分与它的实现部分分离,使它们都可以独立地变化。在桥接模式中的桥接是单向的,也就是只能是抽象部分的对象去使用具体实现部分的对象,而不能反过来,也就是个单向桥。

    2、案例分析

    (1)需求:发送提示消息,从业务上看,消息又分成普通消息、加急消息和特急消息多种,不同的消息类型,业务功能处理是不一样的,比如加急消息是在消息上添加加急,而特急消息除了添加特急外,还会做一条催促的记录,多久不完成会继续催促。从发送消息的手段上看,又有系统内短消息、手机短消息、邮件等等。

    (2)普通的解决方案:通过继承来扩展

    缺点:扩展消息的种类较为麻烦,不同的消息种类(CommonMessage、UrgencyMessage、SpecialUrgencymessage)具有不同的业务,每个种类的消息需要实现所有不同的消息发送方式,另外新增一种消息的发送方式(SMS、Email、Mobile),也需要所有的消息种类更改,加入这种新的发送方式的实现

    (3)应用桥接模式的解决思路

    1)分析功能要求:示例的变化具有两个纬度

    一个纬度是抽象的消息这边,包括普通消息、加急消息和特急消息,这几个抽象的消息本身就具有一定的关系,加急消息和特急消息会扩展普通消息;另一个纬度在具体的消息发送方式上,包括站内短消息、Email和手机短信息,这几个方式是平等的,可被切换的方式。

    2)问题的根本原因:消息的抽象和实现是混杂在一起,一个纬度的变化,会引起另一个纬度进行相应的变化,从而使得程序扩展起来非常困难。

    3)桥接模式解决思路:引入实现的接口,把实现部分从系统中分离出去

    // 1、实现发送消息的统一接口 public interface MessageImplementor { /* * 发送消息 * @param message 要发送的消息内容 * @param toUser 消息发送的目的人员 */ public void send(String message,String toUser); } // 2、定义抽象的消息对象 public abstract class AbstractMessage { // 持有一个实现部分的对象 protected MessageImplementor impl; // 构造方法,传入实现部分的对象,impl 是实现部分的对象 public AbstractMessage(MessageImplementor impl){ this.impl = impl; } // 发送消息,转调实现部分的方法 public void sendMessage(String message,String toUser){ this.impl.send(message, toUser); } } // 3、真正的具体实现对象 public class MessageSMS implements MessageImplementor{ public void send(String message, String toUser) { System.out.println("使用站内短消息的方式,发送消息'"+message+"'给"+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); } } // 4、扩充由AbstractMessage定义的接口功能 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) { //获取相应的数据,组织成监控的数据对象,然后返回 } } 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("请喝一杯茶", "小李"); } }

    运行结果如下:

    使用站内短消息的方式,发送消息'请喝一杯茶'给小李 使用站内短消息的方式,发送消息'加急:请喝一杯茶'给小李 使用站内短消息的方式,发送消息'特急:请喝一杯茶'给小李 使用手机短消息的方式,发送消息'请喝一杯茶'给小李 使用手机短消息的方式,发送消息'加急:请喝一杯茶'给小李 使用手机短消息的方式,发送消息'特急:请喝一杯茶'给小李

    3、扩展

    (1)桥接的作用

    通过桥接让抽象部分拥有实现部分的接口对象,在抽象部分就可以通过这个接口来调用具体实现部分的功能。使得抽象和实现可以独立变化,都可以分别扩充。抽象部分使用实现部分对外接口的程序动态变换,同一个真实实现可以被不同的抽象对象使用,反过来,同一个抽象也可以有多个不同的实现,比如:站内短消息的实现功能,可以被普通消息、加急消息或是特急消息等不同的消息对象使用;反过来,某个消息具体的发送方式,可以是站内短消息,或者是Email,也可以是手机短消息等具体的发送方式。桥接模式主要是把继承改成了使用对象组合,从而把两个纬度分开,让每一个纬度单独去变化,最后通过对象组合的方式,把两个纬度组合起来,每一种组合的方式就相当于原来继承中的一种实现,这样就有效的减少了实际实现的类的个数

    (2)对设计原则的体现

    桥接模式很好的实现了开闭原则,抽象部分和实现部分都是可变化的,通常情况下,顶层的Abstraction和Implementor是不变的,而具体的Implementor的实现,是可变的,由于Abstraction是通过接口来操作具体的实现,因此具体的Implementor的实现是可以扩展的,根据需要可以有多个具体的实现。桥接模式还很好的体现了:多用对象组合,少用对象继承

     

    尾注

    上述的总结与思考是基于对《研磨设计模式》这本书的精读与演绎更多及时干货,请关注微信公众号:JAVA万维猿圈

     

    最新回复(0)