bridge

第九章 桥接模式(Bridge Pattern)

1 简介

桥接模式(Bridge Pattern)是一种结构模式(Structural Design Pattern)。面向对象程序设计的一个重要特性是继承(Inheritence)。在开发项目中使用继承能有效帮助开发人员明晰代码逻辑,重用代码功能。然而,由于需求的变化,或者前期代码设计考虑不充分,导致当有一处代码变更时,会引起多处代码的变更。例如,当修改接口(Interface)时,需要同时修改实现该接口的所有类。因此,在给予开发人员诸多好处的同时,继承也将"父子关系"紧紧的绑定在一起。为了解决这个问题,人们设计了桥接模式。

桥接模式能够用于分离抽象层和实现层,使得当抽象层发生变化时,无需修改实现层的内容。如下面的例子所示,我们定义了一个类Message,用于表示一条消息(Message)。TextMessage和EmailMessage继承自Message类,分别用于表示一条文本消息(Text Message)和邮件消息(Email Message)。为了发送文本消息和邮件消息,开发人员可能会选择使用继承特性,进一步扩展TextMessage和EmailMessage。这两个消息发送的实现类为TextMessageSender和EmailMessageSender。

图一 例一的设计结构图

图一 例一的设计结构图

上述的设计并没有什么错。但是,当我们需要修改Message类的接口时,我们需要同时修改TextMessage、EmailMessage、TextMessageSender和EmailMessageSender。另一种可能的情况是,如果我们需要修改TextMessageSender或者EmailMessageSender的接口,那么,我们需要同时修改它们的父类。为了避免这种情况,开发人员可以使用桥接模式,改善上述类之间的关系。

2 桥接模式示例

桥接模式将上述的Message和MessageSender分离,变成如下的结构。Message、TextMessage和EmailMessage保持不变,而TextMessageSender和EmailMessageSender变更为继承自MessageSender接口。下面是变更后的、使用桥接模式实现的代码示例。

图一 桥接模式设计结构图

图一 桥接模式设计设计结构图

Message是一个抽象类,它有一个指向MessageSender的成员变量。TextMessage和EmailMessage类继承自Message类,并覆盖了send()成员方法。

public abstract class Message {
    protected MessageSender sender = null;

    public Message(MessageSender sender) {
        this.sender = sender;
    }

    public abstract void send();
}

public class TextMessage {
    public TextMessage(TextMessageSender sender) {
        super(sender);
    }

    @Override
    public void send() {
        this.sender.send();
    }
}

public class EmailMessage {
    public EmailMessage(EmailMessageSender sender) {
        super(sender);
    }

    @Override
    public void send() {
        this.sender.send();
    }
}

MessageSender是一个接口,定义了成员方法send()。TextMessageSender和EmailMessageSender类实现了MessageSender接口。它们各自实现了发送文本消息和Email的功能。

public interface MessageSender {
    public void send();
}

public class TextMessageSender implements MessageSender {
    @Override
    public void send() {
        System.out.println("Send a text message.");
    }
}

public class EmailMessageSender implements MessageSender {
    @Override
    public void send() {
        System.out.println("Send an email.");
    }
}

因此,当我们使用Message类和MessageSender类时,我们可以分别创建相应的对象,如代码所示。

public class SendMessageClient {
    public static void main(String[] args) {
        EmailMessageSender messageSender = new EmailMessageSender();
        Message message = new EmailMessage(messageSender);
        message.send();
    }
}

最后,我们再来看看桥接模式给我们带来的好处。假设,我们现在增加一项新的需求,发送Email时,需要对Email加密。那么,我们可以新增一个EncryptedEmailMessageSender类,用于加密Email。在客户端,我们创建一个EncryptedEmailMessageSender对象,传入Message对象中。在整个修改的过程中,我们并没有修改Message类,这是因为桥接模式分离了Message类与MessageSender类。

public class EncryptedEmailMessageSender extends EmailMessageSender {
    @Override
    public void send() {
        System.out.println("We can encrypt emails here.");
    }
}

public class SendMessageClient {
    public static void main(String[] args) {
        EncryptedEmailMessageSender messageSender = new EncryptedEmailMessageSender();
        Message message = new EmailMessage(messageSender);
        message.send();
    }
}

3 小结

本章介绍了桥接模式。因为继承关系将抽象层和实现层紧紧的绑定在一起。当抽象层发生变化时,实现层也需要相应的变化。桥接模式分离了抽象层和实现层。所以,当抽象层发生变化时,实现层可以保持不变。反之亦然。

 

上一章
下一章

注册用户登陆后可留言

Copyright  2019 Little Waterdrop, LLC. All Rights Reserved.