第5课_适配器与桥接
热度🔥:66 免费课程
授课语音
适配器模式与桥接模式的区别
适配器模式(Adapter Pattern)和桥接模式(Bridge Pattern)都是结构型设计模式,它们的目标都是通过某种方式将两个不兼容的接口连接起来,使得客户端能够使用它们,但这两种模式的应用场景和设计思想有所不同。
1. 适配器模式(Adapter Pattern)
适配器模式的目的是将一个类的接口转换成客户端所期望的接口,从而使得原本接口不兼容的两个类能够协同工作。适配器模式通常是在现有系统的基础上增加新的功能,目的是“适配”现有接口,使其符合目标接口。
1.1 应用场景
- 当你希望将一个已有的类与另一个接口兼容时,但不希望修改现有的类。
- 在系统中有多个不同的类实现相似的功能,但接口不兼容时。
1.2 设计思想
- 使用适配器来“包裹”原有的类,重新定义一个与目标接口兼容的接口,从而实现对原有类的适配。
- 适配器通常是作为客户端和服务提供者之间的“桥梁”存在,它不改变服务提供者的行为,只改变服务接口的形式。
2. 桥接模式(Bridge Pattern)
桥接模式的目的是将抽象部分与实现部分分离,使得它们可以独立地变化。通过桥接模式,可以在不改变抽象部分的情况下,改变其实现方式,或者在不改变实现部分的情况下,改变抽象部分。
2.1 应用场景
- 需要独立扩展抽象和实现部分的类,并且抽象部分和实现部分都有多个变化维度时。
- 当一个类有多个变化维度,而这些变化维度经常会发生变化时,桥接模式可以有效解决代码爆炸的问题。
2.2 设计思想
- 抽象和实现分离,通过组合的方式将它们关联起来。
- 抽象层定义高层次的接口,而实现层定义具体的实现,两者独立变化,避免了多重继承导致的复杂性。
3. 适配器模式与桥接模式的区别
特性 | 适配器模式(Adapter Pattern) | 桥接模式(Bridge Pattern) |
---|---|---|
主要目的是 | 转换接口,使得不兼容的接口能够协同工作。 | 分离抽象和实现,使得两者可以独立变化。 |
工作方式 | 在客户端和服务提供者之间提供一个适配器,转换接口。 | 使用桥接实现类与抽象类解耦,允许独立变化抽象和实现的维度。 |
应用场景 | 用于两个接口不兼容的情况下。 | 用于有多个维度的变化,且每个维度都有多个变体时。 |
实现形式 | 通过组合现有的类,将其接口转换为目标接口。 | 通过组合抽象类和实现类,解耦它们的变化。 |
是否改变原有类 | 不改变原有类的代码,只是调整接口。 | 不改变原有类的代码,通过桥接方式将抽象部分与实现部分分离。 |
4. 代码示例:适配器模式
4.1 代码案例
// 目标接口
interface MediaPlayer {
void play(String audioType, String fileName);
}
// 被适配的类
class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType) {
if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
}
else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}
else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}
// 高级媒体播放器接口
interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
// 高级媒体播放器的实现类
class VlcPlayer implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file: " + fileName);
}
@Override
public void playMp4(String fileName) {
// 不支持播放 MP4 格式
}
}
class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
// 不支持播放 VLC 格式
}
@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file: " + fileName);
}
}
// 客户端代码
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}
4.2 代码解析
在这个示例中,我们通过 MediaAdapter
类实现了适配器模式,将 MediaPlayer
和 AdvancedMediaPlayer
不兼容的接口适配了起来。通过适配器类,AudioPlayer
客户端可以统一使用 play
方法播放不同格式的音频。
5. 代码示例:桥接模式
5.1 代码案例
// 抽象类
abstract class Shape {
protected DrawingAPI drawingAPI;
protected Shape(DrawingAPI drawingAPI) {
this.drawingAPI = drawingAPI;
}
public abstract void draw();
public abstract void resizeByPercentage(double percentage);
}
// 实现类接口
interface DrawingAPI {
void drawCircle(double x, double y, double radius);
}
// 具体实现类
class DrawingAPI1 implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius) {
System.out.println("Drawing API1 Circle at (" + x + ", " + y + ") with radius " + radius);
}
}
class DrawingAPI2 implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius) {
System.out.println("Drawing API2 Circle at (" + x + ", " + y + ") with radius " + radius);
}
}
// 具体抽象类
class Circle extends Shape {
private double x, y, radius;
public Circle(double x, double y, double radius, DrawingAPI drawingAPI) {
super(drawingAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw() {
drawingAPI.drawCircle(x, y, radius);
}
@Override
public void resizeByPercentage(double percentage) {
radius *= percentage;
}
}
// 客户端代码
public class BridgePatternDemo {
public static void main(String[] args) {
Shape circle1 = new Circle(5, 10, 2, new DrawingAPI1());
Shape circle2 = new Circle(10, 20, 4, new DrawingAPI2());
circle1.draw();
circle2.draw();
}
}
5.2 代码解析
在这个示例中,Shape
类定义了抽象的绘图方法,而 DrawingAPI
接口和它的实现类 DrawingAPI1
和 DrawingAPI2
提供了具体的绘图实现。通过桥接模式,我们将抽象部分 Shape
和实现部分 DrawingAPI
解耦,使得两者可以独立变化。
6. 总结
- 适配器模式 用于转换接口,使得不同接口的类可以协同工作。它通过适配器将现有类的接口转换为目标接口。
- 桥接模式 用于解耦抽象和实现部分,使得它们可以独立变化。它通过组合将抽象和实现部分分开,避免了复杂的继承关系。