结构型模式(三):桥接模式
- 4.桥接模式(Bridge)
- 4.1 结构
- 4.2 示例
- 4.2.1 抽象类
- 4.2.2 细化抽象类
- 4.2.3 实现类接口
- 4.2.4 具体实现类
- 4.2.5 客户端
- 5.外观模式(Facade)
4.桥接模式(Bridge)
桥接模式(Bridge Pattern
)是设计模式中的一种结构型模式,主要用于 将抽象部分与实现部分分离,使它们可以独立变化。这种模式在多种场景下非常有用,尤其是在需要将抽象和实现解耦的情况下。以下是桥接模式的主要特点和应用场景:
- 分离抽象和实现:将抽象部分和实现部分分离,使它们可以独立变化。
- 减少类的爆炸性增长:通过将抽象和实现解耦,可以减少类的数量,提高系统的可维护性。
- 动态切换实现:可以在运行时动态切换实现部分,而不需要修改客户端代码。
4.1 结构
Abstraction
(抽象类):定义抽象类的接口,包含一个对实现部分的引用。RefinedAbstraction
(细化抽象类):扩展抽象类,提供更具体的实现。Implementor
(实现类接口):定义实现类的接口,具体实现类需要实现这个接口。ConcreteImplementor
(具体实现类):实现实现类接口,提供具体的实现。
4.2 示例
假设我们有一个图形绘制系统,需要支持不同的图形(圆形、方形等)和不同的绘制方式(如使用不同的颜色或填充方式)。我们可以使用桥接模式来实现这个系统。
4.2.1 抽象类
// 抽象类
public abstract class Shape {protected DrawAPI drawAPI;protected Shape(DrawAPI drawAPI) {this.drawAPI = drawAPI;}public abstract void draw();
}
4.2.2 细化抽象类
// 细化抽象类
public class Circle extends Shape {private int x, y, radius;public Circle(int x, int y, int radius, DrawAPI drawAPI) {super(drawAPI);this.x = x;this.y = y;this.radius = radius;}@Overridepublic void draw() {drawAPI.drawCircle(x, y, radius);}
}public class Rectangle extends Shape {private int x, y, width, height;public Rectangle(int x, int y, int width, int height, DrawAPI drawAPI) {super(drawAPI);this.x = x;this.y = y;this.width = width;this.height = height;}@Overridepublic void draw() {drawAPI.drawRectangle(x, y, width, height);}
}
4.2.3 实现类接口
// 实现类接口
public interface DrawAPI {void drawCircle(int x, int y, int radius);void drawRectangle(int x, int y, int width, int height);
}
4.2.4 具体实现类
// 具体实现类
public class RedDrawAPI implements DrawAPI {@Overridepublic void drawCircle(int x, int y, int radius) {System.out.println("Drawing Circle [Color: Red, x: " + x + ", y: " + y + ", radius: " + radius);}@Overridepublic void drawRectangle(int x, int y, int width, int height) {System.out.println("Drawing Rectangle [Color: Red, x: " + x + ", y: " + y + ", width: " + width + ", height: " + height);}
}public class BlueDrawAPI implements DrawAPI {@Overridepublic void drawCircle(int x, int y, int radius) {System.out.println("Drawing Circle [Color: Blue, x: " + x + ", y: " + y + ", radius: " + radius);}@Overridepublic void drawRectangle(int x, int y, int width, int height) {System.out.println("Drawing Rectangle [Color: Blue, x: " + x + ", y: " + y + ", width: " + width + ", height: " + height);}
}
4.2.5 客户端
public class BridgePatternDemo {public static void main(String[] args) {Shape redCircle = new Circle(100, 100, 50, new RedDrawAPI());Shape blueRectangle = new Rectangle(10, 10, 100, 100, new BlueDrawAPI());redCircle.draw();blueRectangle.draw();}
}
输出结果:
Drawing BridgePatternDemo.Circle [Color: Red, x: 100, y: 100, radius: 50
Drawing BridgePatternDemo.Rectangle [Color: Blue, x: 10, y: 10, width: 100, height: 100
5.外观模式(Facade)
外观模式(Facade Pattern
)是一种设计模式,用于 为复杂的子系统提供一个简化的接口。它的主要目的是减少客户端与子系统之间的依赖关系,使客户端代码更容易理解和使用。以下是外观模式的几个关键点:
- 简化接口:外观模式通过提供一个统一的高层接口,使客户端代码可以更简单地访问子系统的功能,而不需要了解子系统的内部复杂性。
- 降低耦合度:客户端代码只需与外观类交互,而不必与子系统的多个类直接交互,从而降低了系统的耦合度。
- 提高灵活性:外观类可以灵活地控制对子系统的访问,可以在不改变客户端代码的情况下,修改子系统的实现。
假设你有一个 家庭影院系统,包括 DVD 播放器、投影仪、屏幕、音响等设备。每个设备都有自己的控制接口,如果直接操作这些设备,客户端代码会非常复杂。通过外观模式,可以创建一个家庭影院外观类,提供一个简单的接口来控制整个系统。
public class HomeTheaterFacade {private DvdPlayer dvdPlayer;private Projector projector;private Screen screen;private Amplifier amplifier;public HomeTheaterFacade(DvdPlayer dvdPlayer, Projector projector, Screen screen, Amplifier amplifier) {this.dvdPlayer = dvdPlayer;this.projector = projector;this.screen = screen;this.amplifier = amplifier;}public void watchMovie(String movie) {System.out.println("Get ready to watch a movie...");screen.down();projector.on();dvdPlayer.play(movie);amplifier.on();}public void endMovie() {System.out.println("Shutting movie theater down...");screen.up();projector.off();dvdPlayer.stop();amplifier.off();}
}
通过这个外观类,客户端代码可以非常简单地控制整个家庭影院系统:
public class Client {public static void main(String[] args) {DvdPlayer dvdPlayer = new DvdPlayer();Projector projector = new Projector();Screen screen = new Screen();Amplifier amplifier = new Amplifier();HomeTheaterFacade facade = new HomeTheaterFacade(dvdPlayer, projector, screen, amplifier);facade.watchMovie("The Matrix");facade.endMovie();}
}
这样,客户端代码只需要调用外观类的 watchMovie
和 endMovie
方法,而不需要关心每个设备的具体操作。