• 设计模式——9. 桥接模式


    1. 说明

    桥接模式(Bridge Pattern)是一种结构型设计模式,它用于将抽象部分和具体实现部分分离,以便它们可以独立地变化而不互相影响。桥接模式通过将抽象和实现分离来解决类的多层次继承结构问题,使得系统更加灵活。
    在桥接模式中,有两个关键角色:
    2. 抽象类(Abstraction):定义了抽象部分的接口,通常包含一个成员变量用于持有一个实现对象,并包含抽象方法,这些方法会被委托给实现对象。
    3. 实现类(Implementor):定义了具体实现部分的接口,抽象类中的实现方法都会在这里得以实际实现。
    桥接模式的核心思想是将抽象和实现分开,让它们可以独立变化。这种分离使得可以在不修改现有代码的情况下,为系统添加新的抽象部分和实现部分,从而提高系统的可扩展性。

    桥接模式的目标是提高系统的灵活性和可维护性,但它也增加了系统的复杂性,因此在设计时需要权衡这些因素。

    2. 使用的场景

    桥接模式的使用场景包括:

    1. 多维度变化:当一个类具有多个维度的变化,例如抽象部分(Abstraction)和实现部分(Implementor)都有可能变化,但又不希望通过多层次的继承来组合这些变化时,可以使用桥接模式。
    2. 抽象和实现分离:当希望抽象部分和实现部分能够独立地变化和扩展,而不相互影响时,桥接模式可以帮助实现这种分离。
    3. 避免类的爆炸性增长:当有多个维度的变化,并且使用类的继承关系来处理这些变化会导致类的爆炸性增长时,桥接模式可以避免这种情况,使得系统更容易维护和扩展。
    4. 平台无关性:当希望在不同的平台上重用抽象部分和实现部分,并且这些平台之间的实现可能不同,可以使用桥接模式来实现跨平台的兼容性。
    5. 动态切换实现:当需要在运行时动态地选择不同的实现或算法时,桥接模式可以提供一种灵活的方式来切换实现。
    6. 分层结构:在分层结构中,桥接模式可以用来将不同层次的抽象和实现连接起来,以实现整个系统的模块化和可维护性。

    总之,桥接模式在多个维度的变化和抽象与实现分离的情况下,可以提供一种灵活、可扩展且易于维护的设计方式。它允许在不同维度上独立地变化和扩展组件,从而提高了系统的可扩展性和可维护性。

    3. 应用例子

    以下是一个简单的 Python 示例,演示了如何使用桥接模式。假设我们正在构建一个图形编辑器,其中包含不同类型的形状(如矩形和圆形)和不同的颜色(如红色和蓝色),并且希望能够以灵活的方式组合它们。

    # 实现部分的接口
    class Color:
        def apply_color(self):
            pass
    
    # 具体实现部分 - 红色
    class RedColor(Color):
        def apply_color(self):
            return "红色"
    
    # 具体实现部分 - 蓝色
    class BlueColor(Color):
        def apply_color(self):
            return "蓝色"
    
    # 抽象部分的接口
    class Shape:
        def __init__(self, color):
            self.color = color
    
        def draw(self):
            pass
    
    # 具体抽象部分 - 矩形
    class Rectangle(Shape):
        def draw(self):
            return f"画一个{self.color.apply_color()}的矩形"
    
    # 具体抽象部分 - 圆形
    class Circle(Shape):
        def draw(self):
            return f"画一个{self.color.apply_color()}的圆形"
    
    # 客户端代码
    red_color = RedColor()
    blue_color = BlueColor()
    
    rectangle = Rectangle(red_color)
    circle = Circle(blue_color)
    
    print(rectangle.draw())  # 输出:画一个红色的矩形
    print(circle.draw())     # 输出:画一个蓝色的圆形
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    在这个示例中,Color 表示实现部分的接口,具体的颜色实现部分是 RedColor 和 BlueColor。Shape 表示抽象部分的接口,具体的形状实现部分是 Rectangle 和 Circle。客户端代码可以使用不同的颜色和形状来组合图形,而不需要修改现有的类结构,这体现了桥接模式的灵活性。

    4. 实现要素

    桥接模式的实现要素包括以下部分:

    1. 抽象部分(Abstraction):定义了抽象部分的接口,通常包含一个成员变量用于持有一个实现对象,并包含抽象方法,这些方法会被委托给实现对象。
    2. 具体抽象部分(Concrete Abstraction):继承自抽象部分,实现了抽象部分的接口,通常包含一个构造方法用于初始化实现对象。
    3. 实现部分(Implementor):定义了具体实现部分的接口,抽象部分中的方法都会在这里得以实际实现。
    4. 具体实现部分(Concrete Implementor):继承自实现部分,实现了实现部分的接口,负责具体的实现逻辑。

    5. Java/golang/javascrip/C++ 等语言实现方式

    5.1 Java实现

    上述例子用Java语言实现示例如下:

    // 实现部分的接口
    interface Color {
        String applyColor();
    }
    
    // 具体实现部分 - 红色
    class RedColor implements Color {
        @Override
        public String applyColor() {
            return "红色";
        }
    }
    
    // 具体实现部分 - 蓝色
    class BlueColor implements Color {
        @Override
        public String applyColor() {
            return "蓝色";
        }
    }
    
    // 抽象部分的接口
    abstract class Shape {
        protected Color color;
    
        public Shape(Color color) {
            this.color = color;
        }
    
        abstract String draw();
    }
    
    // 具体抽象部分 - 矩形
    class Rectangle extends Shape {
        public Rectangle(Color color) {
            super(color);
        }
    
        @Override
        String draw() {
            return "画一个" + color.applyColor() + "的矩形";
        }
    }
    
    // 具体抽象部分 - 圆形
    class Circle extends Shape {
        public Circle(Color color) {
            super(color);
        }
    
        @Override
        String draw() {
            return "画一个" + color.applyColor() + "的圆形";
        }
    }
    
    public class BridgePatternExample {
        public static void main(String[] args) {
            Color redColor = new RedColor();
            Color blueColor = new BlueColor();
    
            Shape rectangle = new Rectangle(redColor);
            Shape circle = new Circle(blueColor);
    
            System.out.println(rectangle.draw());  // 输出:画一个红色的矩形
            System.out.println(circle.draw());     // 输出:画一个蓝色的圆形
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    5.2 Golang实现

    上述例子用golang实现示例如下:

    package main
    
    import "fmt"
    
    // 实现部分的接口
    type Color interface {
            ApplyColor() string
    }
    
    // 具体实现部分 - 红色
    type RedColor struct{}
    
    func (r *RedColor) ApplyColor() string {
            return "红色"
    }
    
    // 具体实现部分 - 蓝色
    type BlueColor struct{}
    
    func (b *BlueColor) ApplyColor() string {
            return "蓝色"
    }
    
    // 抽象部分的接口
    type Shape interface {
            Draw() string
    }
    
    // 具体抽象部分 - 矩形
    type Rectangle struct {
            color Color
    }
    
    func (r *Rectangle) Draw() string {
            return fmt.Sprintf("画一个%s的矩形", r.color.ApplyColor())
    }
    
    // 具体抽象部分 - 圆形
    type Circle struct {
            color Color
    }
    
    func (c *Circle) Draw() string {
            return fmt.Sprintf("画一个%s的圆形", c.color.ApplyColor())
    }
    
    func main() {
            redColor := &RedColor{}
            blueColor := &BlueColor{}
    
            rectangle := &Rectangle{color: redColor}
            circle := &Circle{color: blueColor}
    
            fmt.Println(rectangle.Draw()) // 输出:画一个红色的矩形
            fmt.Println(circle.Draw())    // 输出:画一个蓝色的圆形
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    5.3 Javascript实现

    上述例子用javascript实现示例如下:

    // 实现部分的接口
    class Color {
      applyColor() {
        return "";
      }
    }
    
    // 具体实现部分 - 红色
    class RedColor extends Color {
      applyColor() {
        return "红色";
      }
    }
    
    // 具体实现部分 - 蓝色
    class BlueColor extends Color {
      applyColor() {
        return "蓝色";
      }
    }
    
    // 抽象部分的接口
    class Shape {
      constructor(color) {
        this.color = color;
      }
    
      draw() {}
    }
    
    // 具体抽象部分 - 矩形
    class Rectangle extends Shape {
      draw() {
        return `画一个${this.color.applyColor()}的矩形`;
      }
    }
    
    // 具体抽象部分 - 圆形
    class Circle extends Shape {
      draw() {
        return `画一个${this.color.applyColor()}的圆形`;
      }
    }
    
    // 客户端代码
    const redColor = new RedColor();
    const blueColor = new BlueColor();
    
    const rectangle = new Rectangle(redColor);
    const circle = new Circle(blueColor);
    
    console.log(rectangle.draw()); // 输出:画一个红色的矩形
    console.log(circle.draw());    // 输出:画一个蓝色的圆形
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    5.4 C++实现

    上述例子用C++实现如下:

    #include 
    #include 
    
    // 实现部分的接口
    class Color {
    public:
        virtual std::string applyColor() = 0;
    };
    
    // 具体实现部分 - 红色
    class RedColor : public Color {
    public:
        std::string applyColor() override {
            return "红色";
        }
    };
    
    // 具体实现部分 - 蓝色
    class BlueColor : public Color {
    public:
        std::string applyColor() override {
            return "蓝色";
        }
    };
    
    // 抽象部分的接口
    class Shape {
    protected:
        Color* color;
    
    public:
        Shape(Color* color) : color(color) {}
    
        virtual std::string draw() = 0;
    };
    
    // 具体抽象部分 - 矩形
    class Rectangle : public Shape {
    public:
        Rectangle(Color* color) : Shape(color) {}
    
        std::string draw() override {
            return "画一个" + color->applyColor() + "的矩形";
        }
    };
    
    // 具体抽象部分 - 圆形
    class Circle : public Shape {
    public:
        Circle(Color* color) : Shape(color) {}
    
        std::string draw() override {
            return "画一个" + color->applyColor() + "的圆形";
        }
    };
    
    int main() {
        Color* redColor = new RedColor();
        Color* blueColor = new BlueColor();
    
        Shape* rectangle = new Rectangle(redColor);
        Shape* circle = new Circle(blueColor);
    
        std::cout << rectangle->draw() << std::endl; // 输出:画一个红色的矩形
        std::cout << circle->draw() << std::endl;    // 输出:画一个蓝色的圆形
    
        delete redColor;
        delete blueColor;
        delete rectangle;
        delete circle;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    6. 练习题

    假设你正在开发一个图形编辑器应用程序,并且你希望支持不同的操作系统(如 Windows、macOS 和 Linux)和不同的绘图库(如 OpenGL 和 DirectX)。使用桥接模式设计一个系统,使得你可以轻松地添加新的操作系统和绘图库的组合,同时确保它们能够协同工作。

    要求:

    1. 创建一个抽象类 OperatingSystem,它包含一个抽象方法 draw() 用于绘制图形。
    2. 创建具体的操作系统类,如 WindowsOS 和 MacOS,它们继承自 OperatingSystem 并实现 draw() 方法。
    3. 创建一个抽象类 GraphicsLibrary,它包含一个抽象方法 render() 用于渲染图形。
    4. 创建具体的绘图库类,如 OpenGLLibrary 和 DirectXLibrary,它们继承自 GraphicsLibrary 并实现 render() 方法。
    5. 创建一个 Shape 类,它包含一个成员变量 os(表示操作系统)和一个成员变量 graphics(表示绘图库)。它还包含一个抽象方法 drawShape(),该方法在操作系统上绘制图形使用绘图库。
    6. 创建具体的图形类,如 Circle 和 Rectangle,它们继承自 Shape 并实现 drawShape() 方法,以便在指定的操作系统上使用指定的绘图库绘制图形。
    7. 最后,创建一个客户端应用程序,演示如何使用桥接模式创建不同的操作系统和绘图库组合,以绘制不同的图形。

    你可以使用 C++、Java、Python 或任何其他编程语言来实现这个练习。
    你可以在评论区里或者私信我回复您的答案,这样我或者大家都能帮你解答,期待着你的回复~

  • 相关阅读:
    【基于ChatGPT大模型】GIS应用、数据清洗、统计分析、论文助手、项目基金助手、科研绘图、AI绘图
    图片隐写之LSB(Least Significant Bit)原理及其代码实现
    【面试题】作用域和闭包
    Nginx的核心配置文件
    AIGC重塑金融:AI大模型驱动的金融变革与实践
    将博客搬至CSDN
    HackTheBox-Starting Point--Tier 0---Preignition
    合并石子问题-区间dp总结
    Sigrity仿真之电热混合仿真
    相机标定 >> 坐标系转换@内参、外参
  • 原文地址:https://blog.csdn.net/guohuang/article/details/133500978