结构型-桥接模式

1. 项目结构

bash 复制代码
	bridge-pattern-demo/
	├── pom.xml
	├── src/
	│   ├── main/
	│   │   ├── java/
	│   │   │   └── com/
	│   │   │       └── example/
	│   │   │           └── bridge/
	│   │   │               ├── abstraction/
	│   │   │               │   ├── Shape.java
	│   │   │               │   ├── Circle.java
	│   │   │               │   └── Rectangle.java
	│   │   │               ├── implementation/
	│   │   │               │   ├── Color.java
	│   │   │               │   ├── RedColor.java
	│   │   │               │   ├── BlueColor.java
	│   │   │               │   ├── GreenColor.java
	│   │   │               │   └── GradientColor.java
	│   │   │               ├── refinedabstraction/
	│   │   │               │   └── Triangle.java
	│   │   │               └── Main.java
	│   └── test/
	│       └── java/
	│           └── com/
	│               └── example/
	│                   └── bridge/
	│                       └── BridgePatternTest.java

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>bridge-pattern-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>Bridge Pattern Demo</name>
    <description>Demonstration of Bridge Design Pattern in Java</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.13.2</junit.version>
        <mockito.version>3.12.4</mockito.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>${mockito.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2. 代码实现

Shape.java - 抽象形状类

java 复制代码
package com.example.bridge.abstraction;

import com.example.bridge.implementation.Color;

/**
 * 抽象部分:形状
 * 包含对实现部分的引用
 */
public abstract class Shape {
    
    protected Color color; // 桥接接口
    
    public Shape(Color color) {
        this.color = color;
    }
    
    /**
     * 抽象方法:绘制形状
     */
    public abstract void draw();
    
    /**
     * 计算面积
     */
    public abstract double calculateArea();
    
    /**
     * 获取形状描述
     */
    public abstract String getDescription();
    
    /**
     * 应用颜色
     */
    public void applyColor() {
        System.out.println(getDescription() + " 应用颜色: ");
        color.applyColor();
    }
    
    /**
     * 设置新的颜色(运行时改变实现)
     */
    public void setColor(Color color) {
        this.color = color;
        System.out.println("形状颜色已更新");
    }
    
    /**
     * 获取当前颜色信息
     */
    public String getColorInfo() {
        return color.getColorInfo();
    }
}

Circle.java - 具体圆形类

java 复制代码
package com.example.bridge.abstraction;

import com.example.bridge.implementation.Color;

/**
 * 具体抽象部分:圆形
 */
public class Circle extends Shape {
    
    private double radius;
    
    public Circle(Color color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制圆形,半径: " + radius);
        applyColor();
    }
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public String getDescription() {
        return "圆形(半径=" + radius + ")";
    }
    
    public double getRadius() {
        return radius;
    }
    
    public void setRadius(double radius) {
        this.radius = radius;
    }
    
    /**
     * 计算周长
     */
    public double calculatePerimeter() {
        return 2 * Math.PI * radius;
    }
}

Rectangle.java - 具体矩形类

java 复制代码
package com.example.bridge.abstraction;

import com.example.bridge.implementation.Color;

/**
 * 具体抽象部分:矩形
 */
public class Rectangle extends Shape {
    
    private double width;
    private double height;
    
    public Rectangle(Color color, double width, double height) {
        super(color);
        this.width = width;
        this.height = height;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制矩形,宽: " + width + ", 高: " + height);
        applyColor();
    }
    
    @Override
    public double calculateArea() {
        return width * height;
    }
    
    @Override
    public String getDescription() {
        return "矩形(宽=" + width + ", 高=" + height + ")";
    }
    
    /**
     * 计算对角线长度
     */
    public double calculateDiagonal() {
        return Math.sqrt(width * width + height * height);
    }
    
    /**
     * 计算周长
     */
    public double calculatePerimeter() {
        return 2 * (width + height);
    }
    
    public double getWidth() {
        return width;
    }
    
    public void setWidth(double width) {
        this.width = width;
    }
    
    public double getHeight() {
        return height;
    }
    
    public void setHeight(double height) {
        this.height = height;
    }
}

Color.java - 颜色接口

java 复制代码
package com.example.bridge.implementation;

/**
 * 实现部分接口:颜色
 * 定义实现部分的接口
 */
public interface Color {
    
    /**
     * 应用颜色
     */
    void applyColor();
    
    /**
     * 获取颜色信息
     */
    String getColorInfo();
    
    /**
     * 获取颜色代码
     */
    String getColorCode();
    
    /**
     * 检查颜色是否可用
     */
    default boolean isAvailable() {
        return true;
    }
    
    /**
     * 获取颜色透明度
     */
    default double getOpacity() {
        return 1.0;
    }
}

RedColor.java - 红色实现

java 复制代码
package com.example.bridge.implementation;

/**
 * 具体实现:红色
 */
public class RedColor implements Color {
    
    @Override
    public void applyColor() {
        System.out.println("应用红色");
    }
    
    @Override
    public String getColorInfo() {
        return "红色";
    }
    
    @Override
    public String getColorCode() {
        return "#FF0000";
    }
    
    @Override
    public double getOpacity() {
        return 0.9;
    }
    
    /**
     * 红色特有的方法
     */
    public void showWarning() {
        System.out.println("⚠️ 注意:这是警告色");
    }
}

BlueColor.java - 蓝色实现

java 复制代码
package com.example.bridge.implementation;

/**
 * 具体实现:蓝色
 */
public class BlueColor implements Color {
    
    @Override
    public void applyColor() {
        System.out.println("应用蓝色");
    }
    
    @Override
    public String getColorInfo() {
        return "蓝色";
    }
    
    @Override
    public String getColorCode() {
        return "#0000FF";
    }
    
    @Override
    public double getOpacity() {
        return 0.8;
    }
    
    /**
     * 蓝色特有的方法
     */
    public void showCalm() {
        System.out.println("🌊 蓝色代表平静与稳定");
    }
}

GreenColor.java - 绿色实现

java 复制代码
package com.example.bridge.implementation;

/**
 * 具体实现:绿色
 */
public class GreenColor implements Color {
    
    @Override
    public void applyColor() {
        System.out.println("应用绿色");
    }
    
    @Override
    public String getColorInfo() {
        return "绿色";
    }
    
    @Override
    public String getColorCode() {
        return "#00FF00";
    }
    
    @Override
    public double getOpacity() {
        return 0.85;
    }
    
    /**
     * 绿色特有的方法
     */
    public void showEcoFriendly() {
        System.out.println("🌿 绿色代表环保与自然");
    }
}

GradientColor.java - 渐变色实现

java 复制代码
package com.example.bridge.implementation;

/**
 * 具体实现:渐变色
 * 演示更复杂的实现
 */
public class GradientColor implements Color {
    
    private String primaryColor;
    private String secondaryColor;
    
    public GradientColor(String primaryColor, String secondaryColor) {
        this.primaryColor = primaryColor;
        this.secondaryColor = secondaryColor;
    }
    
    @Override
    public void applyColor() {
        System.out.println("应用渐变色: " + primaryColor + " -> " + secondaryColor);
    }
    
    @Override
    public String getColorInfo() {
        return "渐变色(" + primaryColor + "到" + secondaryColor + ")";
    }
    
    @Override
    public String getColorCode() {
        return "Gradient from " + primaryColor + " to " + secondaryColor;
    }
    
    @Override
    public double getOpacity() {
        return 0.75;
    }
    
    /**
     * 设置渐变方向
     */
    public void setGradientDirection(String direction) {
        System.out.println("设置渐变方向: " + direction);
    }
    
    /**
     * 获取渐变信息
     */
    public String getGradientInfo() {
        return "渐变: " + primaryColor + " 到 " + secondaryColor;
    }
    
    public String getPrimaryColor() {
        return primaryColor;
    }
    
    public void setPrimaryColor(String primaryColor) {
        this.primaryColor = primaryColor;
    }
    
    public String getSecondaryColor() {
        return secondaryColor;
    }
    
    public void setSecondaryColor(String secondaryColor) {
        this.secondaryColor = secondaryColor;
    }
}

Triangle.java - 三角形类(扩展抽象)

java 复制代码
package com.example.bridge.refinedabstraction;

import com.example.bridge.abstraction.Shape;
import com.example.bridge.implementation.Color;

/**
 * 扩展抽象部分:三角形
 * 可以添加额外的功能
 */
public class Triangle extends Shape {
    
    private double sideA;
    private double sideB;
    private double sideC;
    
    public Triangle(Color color, double sideA, double sideB, double sideC) {
        super(color);
        if (!isValidTriangle(sideA, sideB, sideC)) {
            throw new IllegalArgumentException("边长无法构成有效的三角形");
        }
        this.sideA = sideA;
        this.sideB = sideB;
        this.sideC = sideC;
    }
    
    @Override
    public void draw() {
        System.out.println("绘制三角形,边长: " + sideA + ", " + sideB + ", " + sideC);
        applyColor();
    }
    
    @Override
    public double calculateArea() {
        // 使用海伦公式计算面积
        double s = (sideA + sideB + sideC) / 2;
        return Math.sqrt(s * (s - sideA) * (s - sideB) * (s - sideC));
    }
    
    @Override
    public String getDescription() {
        return "三角形(边长=" + sideA + "," + sideB + "," + sideC + ")";
    }
    
    /**
     * 计算三角形类型
     */
    public String getTriangleType() {
        if (sideA == sideB && sideB == sideC) {
            return "等边三角形";
        } else if (sideA == sideB || sideA == sideC || sideB == sideC) {
            return "等腰三角形";
        } else {
            return "不等边三角形";
        }
    }
    
    /**
     * 判断是否为直角三角形
     */
    public boolean isRightTriangle() {
        double[] sides = {sideA, sideB, sideC};
        java.util.Arrays.sort(sides);
        return Math.abs(sides[2] * sides[2] - (sides[0] * sides[0] + sides[1] * sides[1])) < 0.0001;
    }
    
    /**
     * 计算周长
     */
    public double calculatePerimeter() {
        return sideA + sideB + sideC;
    }
    
    /**
     * 验证三角形是否有效
     */
    private boolean isValidTriangle(double a, double b, double c) {
        return a + b > c && a + c > b && b + c > a;
    }
    
    /**
     * 扩展功能:绘制三角形的高
     */
    public void drawHeight(int baseSide) {
        System.out.println("绘制从顶点到边" + baseSide + "的高");
    }
    
    public double getSideA() {
        return sideA;
    }
    
    public void setSideA(double sideA) {
        this.sideA = sideA;
    }
    
    public double getSideB() {
        return sideB;
    }
    
    public void setSideB(double sideB) {
        this.sideB = sideB;
    }
    
    public double getSideC() {
        return sideC;
    }
    
    public void setSideC(double sideC) {
        this.sideC = sideC;
    }
}

Main.java

java 复制代码
package com.example.bridge;

import com.example.bridge.abstraction.Circle;
import com.example.bridge.abstraction.Rectangle;
import com.example.bridge.implementation.BlueColor;
import com.example.bridge.implementation.GradientColor;
import com.example.bridge.implementation.GreenColor;
import com.example.bridge.implementation.RedColor;
import com.example.bridge.refinedabstraction.Triangle;

/**
 * 桥接模式演示主程序
 */
public class Main {
    public static void main(String[] args) {
        System.out.println("=== 桥接模式演示 ===\n");
        
        // 创建颜色实现
        RedColor red = new RedColor();
        BlueColor blue = new BlueColor();
        GreenColor green = new GreenColor();
        GradientColor gradient = new GradientColor("红色", "黄色");
        
        System.out.println("1. 红色圆形:");
        Circle redCircle = new Circle(red, 5.0);
        redCircle.draw();
        System.out.println("面积: " + redCircle.calculateArea());
        System.out.println("颜色代码: " + redCircle.getColorInfo());
        
        System.out.println("\n2. 蓝色矩形:");
        Rectangle blueRectangle = new Rectangle(blue, 4.0, 6.0);
        blueRectangle.draw();
        System.out.println("面积: " + blueRectangle.calculateArea());
        System.out.println("对角线: " + blueRectangle.calculateDiagonal());
        
        System.out.println("\n3. 绿色三角形:");
        Triangle greenTriangle = new Triangle(green, 3.0, 4.0, 5.0);
        greenTriangle.draw();
        System.out.println("面积: " + greenTriangle.calculateArea());
        System.out.println("三角形类型: " + greenTriangle.getTriangleType());
        System.out.println("是否直角三角形: " + greenTriangle.isRightTriangle());
        
        System.out.println("\n4. 渐变颜色圆形:");
        Circle gradientCircle = new Circle(gradient, 7.0);
        gradientCircle.draw();
        System.out.println("周长: " + gradientCircle.calculatePerimeter());
        
        System.out.println("\n5. 运行时改变颜色(桥接模式的灵活性):");
        System.out.println("初始状态:");
        redCircle.draw();
        
        System.out.println("\n改变颜色为蓝色:");
        redCircle.setColor(blue);
        redCircle.draw();
        
        System.out.println("\n再次改变颜色为渐变色:");
        redCircle.setColor(gradient);
        redCircle.draw();
        
        System.out.println("\n6. 演示扩展功能:");
        // 使用颜色的特有方法
        if (redCircle.getColorInfo().contains("红色")) {
            ((RedColor) redCircle.color).showWarning();
        }
        
        System.out.println("\n7. 创建形状集合:");
        java.util.List<com.example.bridge.abstraction.Shape> shapes = new java.util.ArrayList<>();
        shapes.add(new Circle(red, 3.0));
        shapes.add(new Rectangle(blue, 2.0, 4.0));
        shapes.add(new Triangle(green, 5.0, 5.0, 5.0));
        shapes.add(new Circle(gradient, 6.0));
        
        System.out.println("\n形状集合信息:");
        for (int i = 0; i < shapes.size(); i++) {
            System.out.println("形状 " + (i + 1) + ": " + 
                shapes.get(i).getDescription() + 
                ", 颜色: " + shapes.get(i).getColorInfo() +
                ", 面积: " + String.format("%.2f", shapes.get(i).calculateArea()));
        }
        
        System.out.println("\n8. 计算总面积:");
        double totalArea = shapes.stream()
            .mapToDouble(com.example.bridge.abstraction.Shape::calculateArea)
            .sum();
        System.out.println("总面积: " + String.format("%.2f", totalArea));
        
        System.out.println("\n=== 桥接模式优势演示 ===");
        System.out.println("可以独立扩展形状和颜色:");
        
        // 添加新颜色不需要修改形状类
        System.out.println("\n添加新颜色(黄色):");
        Color yellow = new Color() {
            @Override
            public void applyColor() {
                System.out.println("应用黄色");
            }
            
            @Override
            public String getColorInfo() {
                return "黄色";
            }
            
            @Override
            public String getColorCode() {
                return "#FFFF00";
            }
        };
        
        Circle yellowCircle = new Circle(yellow, 4.0);
        yellowCircle.draw();
        
        // 添加新形状不需要修改颜色类
        System.out.println("\n使用现有颜色创建复杂形状:");
        Rectangle complexRect = new Rectangle(gradient, 8.0, 10.0);
        complexRect.draw();
        gradient.setGradientDirection("水平");
        complexRect.applyColor();
    }
}

BridgePatternTest.java

java 复制代码
package com.example.bridge;

import com.example.bridge.abstraction.Circle;
import com.example.bridge.abstraction.Rectangle;
import com.example.bridge.implementation.BlueColor;
import com.example.bridge.implementation.RedColor;
import com.example.bridge.refinedabstraction.Triangle;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

public class BridgePatternTest {
    
    private RedColor redColor;
    private BlueColor blueColor;
    
    @Before
    public void setUp() {
        redColor = new RedColor();
        blueColor = new BlueColor();
    }
    
    @Test
    public void testCircleWithRedColor() {
        Circle circle = new Circle(redColor, 5.0);
        
        assertEquals("圆形(半径=5.0)", circle.getDescription());
        assertEquals(Math.PI * 25, circle.calculateArea(), 0.001);
        assertEquals("红色", circle.getColorInfo());
    }
    
    @Test
    public void testRectangleWithBlueColor() {
        Rectangle rectangle = new Rectangle(blueColor, 4.0, 6.0);
        
        assertEquals("矩形(宽=4.0, 高=6.0)", rectangle.getDescription());
        assertEquals(24.0, rectangle.calculateArea(), 0.001);
        assertEquals(Math.sqrt(16 + 36), rectangle.calculateDiagonal(), 0.001);
        assertEquals("蓝色", rectangle.getColorInfo());
    }
    
    @Test
    public void testTriangleWithRedColor() {
        Triangle triangle = new Triangle(redColor, 3.0, 4.0, 5.0);
        
        assertEquals("三角形(边长=3.0,4.0,5.0)", triangle.getDescription());
        assertEquals(6.0, triangle.calculateArea(), 0.001);
        assertTrue(triangle.isRightTriangle());
        assertEquals("不等边三角形", triangle.getTriangleType());
        assertEquals("红色", triangle.getColorInfo());
    }
    
    @Test(expected = IllegalArgumentException.class)
    public void testInvalidTriangle() {
        new Triangle(redColor, 1.0, 2.0, 10.0);
    }
    
    @Test
    public void testColorChangeAtRuntime() {
        Circle circle = new Circle(redColor, 3.0);
        assertEquals("红色", circle.getColorInfo());
        
        circle.setColor(blueColor);
        assertEquals("蓝色", circle.getColorInfo());
    }
    
    @Test
    public void testColorImplementationMethods() {
        assertEquals("#FF0000", redColor.getColorCode());
        assertEquals(0.9, redColor.getOpacity(), 0.001);
        assertTrue(redColor.isAvailable());
        
        assertEquals("#0000FF", blueColor.getColorCode());
        assertEquals(0.8, blueColor.getOpacity(), 0.001);
        assertTrue(blueColor.isAvailable());
    }
    
    @Test
    public void testCirclePerimeter() {
        Circle circle = new Circle(redColor, 7.0);
        assertEquals(2 * Math.PI * 7.0, circle.calculatePerimeter(), 0.001);
    }
    
    @Test
    public void testRectanglePerimeter() {
        Rectangle rectangle = new Rectangle(blueColor, 5.0, 3.0);
        assertEquals(16.0, rectangle.calculatePerimeter(), 0.001);
    }
    
    @Test
    public void testTrianglePerimeter() {
        Triangle triangle = new Triangle(redColor, 3.0, 4.0, 5.0);
        assertEquals(12.0, triangle.calculatePerimeter(), 0.001);
    }
    
    @Test
    public void testEquilateralTriangle() {
        Triangle triangle = new Triangle(blueColor, 5.0, 5.0, 5.0);
        assertEquals("等边三角形", triangle.getTriangleType());
    }
    
    @Test
    public void testIsoscelesTriangle() {
        Triangle triangle = new Triangle(redColor, 5.0, 5.0, 7.0);
        assertEquals("等腰三角形", triangle.getTriangleType());
    }
}

3. 构建和运行

构建项目

bash 复制代码
# 在项目根目录执行
mvn clean compile

运行主程序

bash 复制代码
mvn exec:java -Dexec.mainClass="com.example.bridge.Main"

运行测试

bash 复制代码
mvn test

打包项目

bash 复制代码
mvn package

4. 核心概念

  • 桥接模式的组成:

    • Abstraction(抽象部分):定义抽象接口,维护对实现部分的引用

    • RefinedAbstraction(扩展抽象部分):扩展抽象部分接口

    • Implementor(实现部分接口):定义实现部分的接口

    • ConcreteImplementor(具体实现):具体实现Implementor接口

  • 桥接模式的优点:

    • 分离抽象和实现:抽象和实现可以独立扩展,不会相互影响

    • 提高系统可扩展性:两个维度都可以独立扩展

    • 实现细节对客户透明:客户不需要知道实现细节

  • 适用场景:

    • 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展

    • 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性

    • 不希望使用继承或因为多层次继承导致系统类的个数急剧增加

    • 需要对抽象化角色和实现化角色进行动态绑定

  • 桥接模式与适配器模式的区别:

    • 适配器模式:关注接口的转换,让两个不兼容的接口可以一起工作

    • 桥接模式:关注抽象和实现的分离,让它们可以独立变化

相关推荐
大连好光景7 小时前
【踩坑】HyperV桥接模式下Ubuntu24.02虚拟机固定IP设置
桥接模式
老朱佩琪!6 天前
Unity桥接模式
unity·设计模式·c#·桥接模式
ZouZou老师15 天前
C++设计模式之桥接模式:以家具生产为例
c++·设计模式·桥接模式
具***717 天前
台达AS系列PLC modbus TCP网口上位机通信,项目现场使用设备的C#源代码
桥接模式
询问QQ6882388618 天前
锂电池主动均衡仿真:基于电压的变压器型均衡电路探索
桥接模式
__万波__18 天前
二十三种设计模式(七)--桥接模式
设计模式·桥接模式
牛奶咖啡1321 天前
解决配置虚拟网络后同网段的设备网络不通问题
网络·桥接模式·主机模式·配置虚拟网络后同网段设备不通·排查解决同网段同网关网络不通·重置windows主机网络·nas模式
雨中飘荡的记忆21 天前
设计模式之桥接模式详解
设计模式·桥接模式
ZHE|张恒1 个月前
设计模式(七)桥接模式 — 抽象与实现分离,让维度独立扩展
设计模式·桥接模式