设计模式-桥接模式


设计模式-桥接模式

定义

桥接模式又叫桥梁模式、接口模式或柄体模式。是将抽象的部分和实现的部分分离开来,使它们可以独立变化

通过组合的方式建立两个类之间的联系,而不是继承。

属于结构型模式。

适用场景

  1. 在抽象和具体实现之间需要增加更多的灵活性的场景。
  2. 一个类存在两个独立变化的维度,而这两个维度都需要独立进行扩展。
  3. 不希望使用继承,或者多层继承导致系统类的个数剧增。

例子

代码示例:

UML 类图:

新建一个IMessage消息接口类,有一个sendMessage 方法:

/**
 * 消息接口类
 * @author black
 *
 */
public interface IMessage {

    /**
     * 发送消息
     * @param message 消息题
     * @param recvUser 接收者
     */
    void sendMessage(String message, String recvUser);
}

根据【消息发送方式】维度,新建邮件消息类:

package com.black.design.pattern.bridge.general;

/**
 * 邮件消息
 * @author black
 *
 */
public class EmailMessage implements IMessage {

    public void sendMessage(String message, String recvUser) {
        System.out.println("发送邮件【"+message+"】给" + recvUser);
    }

}

根据【消息发送方式】维度,新建短信消息类:

package com.black.design.pattern.bridge.general;

/**
 * 短信消息
 * @author black
 *
 */
public class SmsMessage implements IMessage {

    public void sendMessage(String message, String recvUser) {
        System.out.println("发送短信【"+message+"】给" + recvUser);
    }

}

根据【消息类型】维度,新建普通消息类:

package com.black.design.pattern.bridge.general;

/**
 * 普通消息
 * @author black
 *
 */
public class NormalMessage implements IMessage {

    public void sendMessage(String message, String recvUser) {
        message = "【普通】" + message;
        System.out.println("发送"+message+"给" + recvUser);
    }
}

根据【消息类型】维度,新建紧急消息类:

package com.black.design.pattern.bridge.general;
/**
 * 紧急消息
 * @author black
 *
 */
public class EmergencyMessage implements IMessage {

    public void sendMessage(String message, String recvUser) {
        message = "【紧急】" + message;
        System.out.println("发送"+message+"给" + recvUser);
    }

}


这时候,我想在邮件消息或者短信发送时,将消息的紧急程度加上,于是进行以下改造:

  1. 根据【发送消息方式】抽象出一个抽象类
  2. 抽象类构造方法注入 【消息类型】的IMessage接口类
    改造后的UML 类图:

其中,AbstractMessage就是一个桥,通过组合方式,引入了同一接口另一个维度。
改造后代码:

IMessage 接口类不变:

package com.black.design.pattern.bridge.general;

/**
 * 消息接口类
 * @author black
 *
 */
public interface IMessage {

    /**
     * 发送消息
     * @param message 消息题
     * @param recvUser 接收者
     */
    void sendMessage(String message, String recvUser);
}

【发送消息方式】维度抽象出一个 AbstractMessage 抽象类,构造方法注入【消息类型】维度 :


package com.black.design.pattern.bridge.general;

/**
 * 作为桥梁引入【消息类型】
 * @author black
 *
 */
public class AbstractMessage implements IMessage {
  //引入另一变化维度
    private IMessage msgType;
    
    public AbstractMessage(IMessage messageType) {
        this.msgType = messageType;
    }
    
	//调用【消息类型】纬度的sendMessage方法
    public void sendMessage(String message, String recvUser) {
        msgType.sendMessage(message, recvUser);
    }
}

EmailMessage 类继承 AbstractMessage 类,委托父类进行发送消息:

package com.black.design.pattern.bridge.general;

/**
 * 发送消息方式-邮件
 * @author black
 *
 */
public class EmailMessage extends AbstractMessage{

    public EmailMessage(IMessage messageType) {
        super(messageType);
    }

    public void sendMessage(String message, String recvUser) {
	// 添加消息发送方式
        message = "邮件【" + message +"】";
        super.sendMessage(message, recvUser);
    }

}


SmsMessage 类继承 AbstractMessage 类,委托父类进行发送消息:


package com.black.design.pattern.bridge.general;

/**
 * 发送消息方式-短信
 * @author black
 *
 */
public class SmsMessage extends AbstractMessage{

    public SmsMessage(IMessage messageType) {
        super(messageType);
    }

    public void sendMessage(String message, String recvUser) {
	// 添加消息发送方式
        message = "短信【" + message +"】";
        super.sendMessage(message, recvUser);
    }
}

NormalMessage 类不变:

package com.black.design.pattern.bridge.general;

/**
 * 普通消息
 * @author black
 *
 */
public class NormalMessage implements IMessage {

    public void sendMessage(String message, String recvUser) {
        message = "【普通】" + message;
        System.out.println("发送"+message+"给" + recvUser);
    }
}


EmergencyMessage 类不变:

package com.black.design.pattern.bridge.general;
/**
 * 紧急消息
 * @author black
 *
 */
public class EmergencyMessage implements IMessage {

    public void sendMessage(String message, String recvUser) {
        message = "【紧急】" + message;
        System.out.println("发送"+message+"给" + recvUser);
    }

}


测试类:

package com.black.design.pattern.bridge.general;

public class MessageTest {

    public static void main(String[] args) {
        
        //发送普通短信给black
        IMessage normalMsg = new  NormalMessage();
        IMessage sms =  new SmsMessage(normalMsg);
        sms.sendMessage("吃饭了吗?","black");
        
         //发送紧急邮件给black
        IMessage emergencyMsg = new EmergencyMessage();
        IMessage email =  new EmailMessage(emergencyMsg);
        email.sendMessage("赶紧回来吃饭!","black");
    }
}


测试结果:

发送【普通】短信【吃饭了吗?】给black
发送【紧急】邮件【赶紧回来吃饭!】给black

最后,可能发现,这个例子和【装饰器】模式很像,但是仔细看看会发现,【装饰器】模式是通过继承,而【桥接】模式是通过组合模式。

优点

  1. 分离抽象部分和具体实现部分
  2. 提高系统扩展性
  3. 符合开闭原则
  4. 符合合成复用原则

缺点

  1. 增加系统理解与设计难度
  2. 需要正确识别系统中两个独立变化的维度