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接口
-
-
桥接模式的优点:
-
分离抽象和实现:抽象和实现可以独立扩展,不会相互影响
-
提高系统可扩展性:两个维度都可以独立扩展
-
实现细节对客户透明:客户不需要知道实现细节
-
-
适用场景:
-
当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展
-
当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性
-
不希望使用继承或因为多层次继承导致系统类的个数急剧增加
-
需要对抽象化角色和实现化角色进行动态绑定
-
-
桥接模式与适配器模式的区别:
-
适配器模式:关注接口的转换,让两个不兼容的接口可以一起工作
-
桥接模式:关注抽象和实现的分离,让它们可以独立变化
-