桥接设计模式

桥接设计模式

原文: https://howtodoinjava.com/design-patterns/structural/bridge-design-pattern/

桥接设计模式用于将类分解为两个部分(抽象及其实现),以便将来可以相互进化而不会相互影响。 它增加了类抽象与其实现之间的松散耦合。

Table of Contents

Design participants of bridge design pattern
When we need bridge design pattern
Sample problem statement
Solution using bridge design pattern
Final notes

将抽象与其实现分离,以便二者可以独立变化。

桥是“手柄或身体”成语的同义词。 这是一种将实现类封装在接口类内部的设计机制。 前者是身体,后者是手柄。 用户将手柄视为实际类,但工作是在体内完成的。

通过在从抽象到实现的方法调用之间添加一个重定向,可以实现这种分离。

桥接设计模式的设计参与者

Bridge pattern participants

桥接模式参与者

以下参与者构成桥接设计模式。

  1. Abstraction(抽象类)

    它定义了抽象接口,即行为部分。 它还维护实现者参考。

  2. RefinedAbstraction(普通类)

    它扩展了Abstraction定义的接口。

  3. Implementer(接口)

    它定义了实现类的接口。 该接口不需要直接对应于抽象接口,并且可以有很大的不同。 抽象imp提供了一个由Implementer接口提供的操作的实现。

  4. ConcreteImplementor(普通类)

    它实现了Implementer接口。

当我们需要桥接设计模式时

桥接模式是旧建议的应用,“与继承相比更偏向组合”。 当您必须以彼此正交的方式将不同的时间子类化时,它将变得很方便。

例如,假设您要创建具有不同颜色的各种 GUI 形状。 一种解决方案可能是:

Without bridge pattern

不使用桥接模式

但是上述解决方案存在问题。 如果要更改Rectange类别,则可能最终也会更改BlueRectangleRedRectangle – 即使更改是特定于颜色的,也可能需要更改Circle类别。

您可以通过以下方式解耦ShapeColor接口来解决上述问题。

With bridge pattern

使用桥接模式

现在,当您更改任何形状时,颜色将保持不变。 同样,反之亦然。

问题陈述

网桥设计模式最适用于需要提供平台独立性的应用。

假设我们正在设计应用,该应用可以在任何操作系统上下载和存储文件。 我想以这种方式设计系统,将来我应该能够以最小的变化添加更多的平台支持。 此外,如果我想在下载程序类中添加更多支持(例如,仅在 Windows 中删除下载内容),那么它应该不会影响客户端代码以及 linux 下载程序。

使用桥接设计模式的解决方案

由于此问题是与经典平台独立性相关的问题,因此我将使用桥接模式来解决此问题。 我将把下载器组件分为抽象部分和实现部分。

我在这里创建两个接口,FileDownloaderAbstraction表示客户端将与之交互的抽象; FileDownloadImplementor代表实现。 这样,两个层次结构可以独立发展而不会互相影响。

FileDownloaderAbstraction.java

public interface FileDownloaderAbstraction 
{
    public Object download(String path);

    public boolean store(Object object);
}

FileDownloaderAbstractionImpl.java

public class FileDownloaderAbstractionImpl implements FileDownloaderAbstraction {

    private FileDownloadImplementor provider = null;

    public FileDownloaderAbstractionImpl(FileDownloadImplementor provider) {
        super();
        this.provider = provider;
    }

    @Override
    public Object download(String path) 
    {
        return provider.downloadFile(path);
    }

    @Override
    public boolean store(Object object) 
    {
        return provider.storeFile(object);
    }
}

FileDownloadImplementor.java

public interface FileDownloadImplementor
{
    public Object downloadFile(String path);

    public boolean storeFile(Object object);
}

LinuxFileDownloadImplementor.java

public class LinuxFileDownloadImplementor implements FileDownloadImplementor 
{
    @Override
    public Object downloadFile(String path) {
        return new Object();
    }

    @Override
    public boolean storeFile(Object object) {
        System.out.println("File downloaded successfully in LINUX !!");
        return true;
    }
}

WindowsFileDownloadImplementor.java

public class WindowsFileDownloadImplementor implements FileDownloadImplementor 
{
    @Override
    public Object downloadFile(String path) {
        return new Object();
    }

    @Override
    public boolean storeFile(Object object) {
        System.out.println("File downloaded successfully in WINDOWS !!");
        return true;
    }
}

Client.java

public class Client 
{
    public static void main(String[] args) 
    {
        String os = "linux";
        FileDownloaderAbstraction downloader = null;

        switch (os) 
        {
            case "windows":
                downloader = new FileDownloaderAbstractionImpl( new WindowsFileDownloadImplementor() );
                break;

            case "linux":
                downloader = new FileDownloaderAbstractionImpl( new LinuxFileDownloadImplementor() );
                break;

            default:
                System.out.println("OS not supported !!");
        }

        Object fileContent = downloader.download("some path");
        downloader.store(fileContent);
    }
}

Output:

File downloaded successfully in LINUX !!

抽象的更改不会影响实现

现在,假设您要在抽象层添加另一项功能(即删除)。 它也不能强迫现有的实现者和客户进行改变。

FileDownloaderAbstraction.java

public interface FileDownloaderAbstraction 
{
    public Object download(String path);

    public boolean store(Object object);

    public boolean delete(String object);
}

FileDownloaderAbstractionImpl.java

public class FileDownloaderAbstractionImpl implements FileDownloaderAbstraction {

    private FileDownloadImplementor provider = null;

    public FileDownloaderAbstractionImpl(FileDownloadImplementor provider) {
        super();
        this.provider = provider;
    }

    @Override
    public Object download(String path) 
    {
        return provider.downloadFile(path);
    }

    @Override
    public boolean store(Object object) 
    {
        return provider.storeFile(object);
    }

    @Override
    public boolean delete(String object) {
        return false;
    }
}

上述更改并不强迫您对实现器类/接口进行任何更改。

实现中的更改不会影响抽象

假设您要在实现层为客户端不知道的所有下载程序添加删除功能(内部功能)。

FileDownloadImplementor.java

public interface FileDownloadImplementor
{
    public Object downloadFile(String path);

    public boolean storeFile(Object object);

    public boolean delete(String object);
}

LinuxFileDownloadImplementor.java

public class LinuxFileDownloadImplementor implements FileDownloadImplementor 
{
    @Override
    public Object downloadFile(String path) {
        return new Object();
    }

    @Override
    public boolean storeFile(Object object) {
        System.out.println("File downloaded successfully in LINUX !!");
        return true;
    }

    @Override
    public boolean delete(String object) {
        return false;
    }
}

WindowsFileDownloadImplementor.java

public class WindowsFileDownloadImplementor implements FileDownloadImplementor 
{
    @Override
    public Object downloadFile(String path) {
        return new Object();
    }

    @Override
    public boolean storeFile(Object object) {
        System.out.println("File downloaded successfully in LINUX !!");
        return true;
    }

    @Override
    public boolean delete(String object) {
        return false;
    }
}

上面的更改不会影响抽象层,因此客户端完全不会受到影响。

最后的笔记

  1. 桥接模式将抽象与其实现分离,以便两者可以独立变化。
  2. 它主要用于实现平台独立性功能。
  3. 它添加了另一种方法级别重定向以实现该目标。
  4. 将抽象接口发布在单独的继承层次结构中,并将实现放入其自己的继承层次结构中。
  5. 使用桥接模式来实现执行时的绑定。
  6. 使用桥模式来映射正交类层次结构
  7. 桥是预先设计的,以使抽象和实现独立变化。

祝您学习愉快!