[23种设计模式][结构型]24.桥接模式

118 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情

1.桥接(Bridge)模式:

在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。

2.意图:

将抽象部分与实现部分分离,使它们都可以独立的变化

3.桥接模式的构成:

  1. 抽象类(Abstraction):定义抽象类的接口并维护一个Implement(实现抽象类)的对象
  2. 扩充抽象类(Refined Abstraction):扩充由Abstraction定义的接口
  3. 实现抽象类(Implementer):定义实现类的接口,这个接口不一定要与Abstraction接口完全一致,事实上这两个接口可以完全不同,一般来说,Implementer接口仅提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作
  4. 具体实现类(Concrete Implementer):实现Implementer接口

4.适用性:

  • 想要避免抽象方法和其实现方法绑定在一起
  • 抽象接口和其实现都需要扩展出子类以备使用。
  • 变动实现的方法不会影响客户端的调用部分(甚至不用重新编译)

5.桥接模式UML类图:

Image.png

6.桥接模式UML序列图:

Image.png

7.代码示例:

Image.png

实现抽象类:

public interface ImageImp {

    void doPaint(String str);
}

具体实现类:

public class WinImp implements ImageImp {

    @Override
    public void doPaint(String str) {
        System.out.println(str + " at Windows");
    }
}

具体实现类:

public class UnixImp implements ImageImp {

    @Override
    public void doPaint(String str) {
        System.out.println(str + " at Unix");
    }
}

抽象类:

public abstract class Image {

    protected ImageImp imageImp;

    public abstract void method(String str);

    public ImageImp getImageImp() {
        return imageImp;
    }

    public void setImageImp(ImageImp imageImp) {
        this.imageImp = imageImp;
    }
}

扩充抽象类:

public class BMPImage extends Image {

    @Override
    public void method(String str) {
        this.imageImp.doPaint(str);
    }
}

扩充抽象类:

public class GIFImage extends Image {

    @Override
    public void method(String str) {
        this.imageImp.doPaint(str);
    }
}

客户角色:

public class Client {

    public static void main(String[] args) {
        Image bmp = new BMPImage();
        ImageImp winImp = new WinImp();
        bmp.imageImp = winImp;
        bmp.method("paint bmp");

        Image gif = new GIFImage();
        ImageImp unixImp = new UnixImp();
        gif.imageImp = unixImp;
        gif.method("paint gif");

        gif.imageImp = winImp;
        gif.method("paint gif");
    }
}