手撕设计模式——消息推送之系统桥接模式
1.业务需求
大家好,我是菠菜啊,好久不见,今天给大家带来的是——桥接模式。老规矩,在介绍这期内容前,我们先来看看这样的需求:我们现在要做一个消息推送系统,实现纯文本消息和html格式消息的推送,推送方式支持email、短信,我们该怎么实现?

2.代码实现
Talk is cheap,show me your code.
初版实现思路:
假设我们有一个父类Message类(消息类型),从它扩展出俩个子类:TextMessage、HtmlMessage,又要支持email、短信推送方式,那么我们需要共创建4个子类才能覆盖所有组合。

初版代码如下:
//消息基类
public abstract class Message {
abstract void sendMessage(String message);
}
//文本消息类
public class TextMessage extends Message{
@Override
void sendMessage(String message) {
System.out.println("TextMessage:"+message);
}
}
//html消息类
public class HtmlMessage extends Message{
@Override
void sendMessage(String message) {
System.out.println("HtmlMessage:"+message);
}
}
public class HtmlEmailMessage extends HtmlMessage{
@Override
void sendMessage(String message) {
super.sendMessage(message);
System.out.println("send HtmlMessage by eamil");
}
}
public class HtmlSmsMessage extends HtmlMessage{
@Override
void sendMessage(String message) {
super.sendMessage(message);
System.out.println("send HtmlMessage by sms");
}
}
public class TextEmailMessage extends TextMessage{
@Override
void sendMessage(String message) {
super.sendMessage(message);
System.out.println("send TextMessage by eamil");
}
}
public class TextSmsMessage extends TextMessage{
@Override
void sendMessage(String message) {
super.sendMessage(message);
System.out.println("send TextMessage by sms");
}
}
public class Client {
public static void main(String[] args) {
Message message = new TextSmsMessage();
message.sendMessage("hello world");
Message message2 = new HtmlEmailMessage();
message2.sendMessage("<html> <h>hello world </h></html>");
}
}
输出结果:

思考:
上述每添加一种消息类型或者消息推送方式,都要新增一个维度的子类,导致类爆炸。而且我们发现消息类型和消息推送方式是俩种独立维度,我们不应该用继承的这种方式去拓展,那么该怎么解决呢?
3.代码优化
//发送方式
public interface MessageSender {
void send(String message);
}
//短信发送方式
public class SmsMessageSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("使用sms发送消息:" + message);
}
}
//eamil发送方式
public class EmailMessageSender implements MessageSender {
@Override
public void send(String message) {
System.out.println("使用email发送消息:" + message);
}
}
//消息类
public abstract class Message2 {
protected MessageSender messageSender;
public Message2(MessageSender messageSender) {
this.messageSender = messageSender;
}
abstract void sendMessage(String message);
}
//文本消息类
public class TextMessage2 extends Message2{
public TextMessage2(MessageSender messageSender) {
super(messageSender);
}
@Override
void sendMessage(String message) {
System.out.println("TextMessage:"+message);
messageSender.send(message);
}
}
//html消息类
public class HtmlMessage2 extends Message2{
public HtmlMessage2(MessageSender messageSender) {
super(messageSender);
}
@Override
void sendMessage(String message) {
System.out.println("HtmlMessage:"+message);
messageSender.send(message);
}
}
输出结果:

实现代码结构图:

思考:
上述将发送消息方式抽象出来,消息类中消息的发送方式委托给MessageSender,通过组合的方式实现消息类型(文本、HTML、模板、紧急)和发送渠道(邮件、短信、推送、微信)这两个维度的独立变化,职责清晰,扩展性强。这个设计模式完全体现了设计原则中的合成复用原则(Composite Reuse Principle):“优先使用对象组合(Composition),而不是类继承(Inheritance)来实现代码复用。”
4.定义与组成

定义:
桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们可以独立地变化。
核心思想:
通过组合替代继承,将抽象(功能层次)与实现(平台层次)解耦,解决多维变化导致的类爆炸问题。
组成部分:
-
抽象部分(Abstraction):定义高层控制逻辑的接口,并且持有实现部分的引用
-
精确抽象(Refined Abstraction):扩展抽象功能的子类
-
实现者接口(Implementor):定义底层实现的契约
-
具体实现者(Concrete Implementor):具体的底层实现
5.典型应用
1)JDBC驱动程序(源码简化)
//实现者接口 - Driver
public interface Driver {
Connection connect(String url, Properties info) throws SQLException;
boolean acceptsURL(String url);
}
//具体实现者 - MySQLDriver
public class MySQLDriver implements Driver {
@Override
public Connection connect(String url, Properties info) {
if (!acceptsURL(url)) return null;
// 实际建立物理连接
Socket socket = new Socket(extractHost(url), extractPort(url));
return new MySQLConnectionImpl(socket);
}
private String extractHost(String url) { /* 解析主机名 */ }
private int extractPort(String url) { /* 解析端口号 */ }
}
//抽象接口 - Connection
public interface Connection extends AutoCloseable {
Statement createStatement() throws SQLException;
PreparedStatement prepareStatement(String sql) throws SQLException;
// ... 其他抽象方法
}
//精确抽象 - MySQLConnectionImpl
class MySQLConnectionImpl implements Connection {
private final Socket socket;
private final OutputStream out;
private final InputStream in;
public MySQLConnectionImpl(Socket socket) {
this.socket = socket;
this.out = socket.getOutputStream();
this.in = socket.getInputStream();
}
@Override
public Statement createStatement() {
return new MySQLStatementImpl(this);
}
// 实际发送SQL命令到MySQL服务器
void sendCommand(String command) {
out.write(command.getBytes());
out.flush();
}
// ... 其他具体实现
}
//桥接点 - DriverManager
public class DriverManager {
private static final List<Driver> drivers = new CopyOnWriteArrayList<>();
public static void registerDriver(Driver driver) {
drivers.add(driver);
}
public static Connection getConnection(String url, String user, String pass) {
for (Driver driver : drivers) {
if (driver.acceptsURL(url)) {
Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", pass);
return driver.connect(url, props);
}
}
throw new SQLException("No suitable driver found");
}
}
2)GUI开发(AWT/Swing)
windows类中有抽象的窗口接口,并有一个画窗口的方法,实现不同平台画窗口功能委托给具体的平台实现
// 抽象:Window
public class Window {
private WindowImpl impl; // 桥接关键
public void draw() {
impl.deviceDraw(); // 委托给具体平台实现
}
}
// 实现:不同OS的图形实现
interface WindowImpl {
void deviceDraw();
}
class WindowsWindowImpl implements WindowImpl {...}
class MacWindowImpl implements WindowImpl {...}
6.适用场景
| 场景特征 | 示例 |
|---|---|
| 存在多个独立变化维度 | 图形形状 × 渲染方式 |
| 需要运行时切换实现 | 动态切换支付渠道 |
| 避免永久绑定抽象与实现 | JDBC连接不同数据库 |
| 类层次结构爆炸 | 避免创建 N×M 子类组合 |
经验法则:当听到"需要根据不同平台/方式做不同实现"时,优先考虑桥接模式
技术需要沉淀,同样生活也是~
个人链接:博客,欢迎一起交流











This is a perfect illustration of the Open/Closed Principle! The combinatorial explosion problem (Text/HTML * Email/SMS) highlights how decoupling interfaces (Message and Channel) is crucial for scalable architecture. This pattern’s value extends beyond code, optimizing everything from marketing funnels to even choosing the right platform for entertainment, like finding a stable jl57 slot experience. Excellent deep dive!
After testing multiple SE Asian platforms, I found Lucky Taya’s secure environment impressive; try their diverse slots and live dealer games at lucky taya club for a seamless mobile experience today.
This demonstration of the Bridge Pattern is excellent! It perfectly illustrates decoupling interfaces (Message Type and Channel). This architectural principle is crucial in any complex system, whether it’s handling message delivery or managing diverse offerings like the various ph 799 games available. Separating the ‘what’ from the ‘how’ ensures scalability and maintainability across all domains.
Honestly, I was skeptical, but your breakdown on prediction models is surprisingly solid. The depth here is legit. Check out Paldo Plus download apk for more action; it actually complements the analysis!