当前位置: 首页 > news >正文

设计模式-桥接模式 - MaC

什么是桥接模式?

桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。桥接模式通过组合关系代替继承关系,降低了抽象和实现这两个可变维度的耦合度。
桥接模式包含以下角色:

  • 抽象部分(Abstract):定义抽象接口,通常包含指向实现部分的引用
  • 细化抽象部分(Refined Abstract):扩展抽象部分,提供更具体的实现
  • 实现部分(Implementor):定义实现接口,通常是一个接口或抽象类
  • 具体实现部分(Concrete Implementor):实现Implementor接口的具体实现

桥接模式的优缺点

优点:

  • 分离抽象和实现:抽象部分和实现部分可以独立开发和变化
  • 提高可扩展性:可以独立地扩展抽象部分和实现部分
    符合开闭原则:新增抽象或实现时无需修改现有代码
  • 隐藏实现细节:客户端不需要关心具体实现细节
  • 减少子类数量:避免了多重继承导致的子类爆炸问题

缺点:

  • 增加系统复杂度:需要正确识别系统中两个独立变化的维度
  • 设计难度增加:需要在设计阶段就识别出抽象和实现部分
  • 可能影响性能:通过组合方式实现功能,可能比直接继承方式稍慢

什么场景下使用桥接模式

  1. 不希望在抽象和实现部分之间有固定的绑定关系
  2. 类的抽象和实现都应该可以通过生成子类的方法加以扩充
  3. 对一个抽象的实现部分的修改应对客户不产生影响
  4. 想在带有不同抽象接口的多个对象之间共享实现
  5. 想在运行时刻切换不同的实现

代码举例

其实在实际开发当中能用到的桥接模式还说很多的,比如spring中的jdbc,日志框架等一些经典的开源框架中都有用到。我认为想真正在实际开发当中用到这些设计模式代码到例子必须在一个功能下举例更好,下面简单以日志输出举例

/ 实现部分接口 - 日志输出API
public interface LogAppender {void append(String level, String message, Throwable throwable);void append(String level, String message);void flush();void close();
}// 具体实现部分 - 控制台日志输出
public class ConsoleLogAppender implements LogAppender {private PrintWriter writer;public ConsoleLogAppender() {this.writer = new PrintWriter(System.out, true);}@Overridepublic void append(String level, String message, Throwable throwable) {writer.printf("[%s] %s%n", level, message);if (throwable != null) {throwable.printStackTrace(writer);}writer.flush();}@Overridepublic void append(String level, String message) {append(level, message, null);}@Overridepublic void flush() {writer.flush();}@Overridepublic void close() {writer.close();}
}// 具体实现部分 - 文件日志输出
public class FileLogAppender implements LogAppender {private PrintWriter writer;private String fileName;public FileLogAppender(String fileName) {this.fileName = fileName;try {this.writer = new PrintWriter(new FileWriter(fileName, true), true);} catch (IOException e) {throw new RuntimeException("无法创建日志文件: " + fileName, e);}}@Overridepublic void append(String level, String message, Throwable throwable) {String timestamp = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date());writer.printf("[%s] [%s] %s%n", timestamp, level, message);if (throwable != null) {throwable.printStackTrace(writer);}}@Overridepublic void append(String level, String message) {append(level, message, null);}@Overridepublic void flush() {writer.flush();}@Overridepublic void close() {writer.close();}public String getFileName() {return fileName;}
}// 具体实现部分 - 数据库日志输出
public class DatabaseLogAppender implements LogAppender {private DataSource dataSource;private String tableName;public DatabaseLogAppender(DataSource dataSource, String tableName) {this.dataSource = dataSource;this.tableName = tableName;}@Overridepublic void append(String level, String message, Throwable throwable) {String sql = "INSERT INTO " + tableName + " (log_level, log_message, log_time, throwable_info) VALUES (?, ?, ?, ?)";try (Connection conn = dataSource.getConnection();PreparedStatement stmt = conn.prepareStatement(sql)) {stmt.setString(1, level);stmt.setString(2, message);stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));stmt.setString(4, throwable != null ? throwable.toString() : null);stmt.executeUpdate();} catch (SQLException e) {// 为避免循环日志,这里简单处理System.err.println("数据库日志写入失败: " + e.getMessage());}}@Overridepublic void append(String level, String message) {append(level, message, null);}@Overridepublic void flush() {// 数据库操作自动提交,无需特殊处理}@Overridepublic void close() {// 数据库连接由连接池管理,这里不关闭}
}// 抽象部分 - 日志记录器
public abstract class Logger {protected LogAppender appender;protected String name;protected boolean enabled;public Logger(String name, LogAppender appender) {this.name = name;this.appender = appender;this.enabled = true;}public abstract void debug(String message);public abstract void info(String message);public abstract void warn(String message);public abstract void error(String message);public abstract void error(String message, Throwable throwable);public void setEnabled(boolean enabled) {this.enabled = enabled;}public boolean isEnabled() {return enabled;}protected void log(String level, String message) {if (enabled) {appender.append(level, String.format("[%s] %s", name, message));}}protected void log(String level, String message, Throwable throwable) {if (enabled) {appender.append(level, String.format("[%s] %s", name, message), throwable);}}
}// 细化抽象部分 - 简单日志记录器
public class SimpleLogger extends Logger {public SimpleLogger(String name, LogAppender appender) {super(name, appender);}@Overridepublic void debug(String message) {log("DEBUG", message);}@Overridepublic void info(String message) {log("INFO", message);}@Overridepublic void warn(String message) {log("WARN", message);}@Overridepublic void error(String message) {log("ERROR", message);}@Overridepublic void error(String message, Throwable throwable) {log("ERROR", message, throwable);}
}// 细化抽象部分 - 带级别的日志记录器
public class LevelLogger extends Logger {public enum LogLevel {DEBUG(0), INFO(1), WARN(2), ERROR(3);private final int level;LogLevel(int level) {this.level = level;}public int getLevel() {return level;}}private LogLevel currentLevel = LogLevel.INFO;public LevelLogger(String name, LogAppender appender) {super(name, appender);}public void setLevel(LogLevel level) {this.currentLevel = level;}@Overridepublic void debug(String message) {if (currentLevel.getLevel() <= LogLevel.DEBUG.getLevel()) {log("DEBUG", message);}}@Overridepublic void info(String message) {if (currentLevel.getLevel() <= LogLevel.INFO.getLevel()) {log("INFO", message);}}@Overridepublic void warn(String message) {if (currentLevel.getLevel() <= LogLevel.WARN.getLevel()) {log("WARN", message);}}@Overridepublic void error(String message) {if (currentLevel.getLevel() <= LogLevel.ERROR.getLevel()) {log("ERROR", message);}}@Overridepublic void error(String message, Throwable throwable) {if (currentLevel.getLevel() <= LogLevel.ERROR.getLevel()) {log("ERROR", message, throwable);}}
}// 工具类工厂 - 简化使用
public class LoggerFactory {private static final Map<String, Logger> loggerCache = new ConcurrentHashMap<>();public static Logger getLogger(String name, String appenderType, Object... config) {String key = name + "_" + appenderType;return loggerCache.computeIfAbsent(key, k -> createLogger(name, appenderType, config));}public static Logger getLogger(Class<?> clazz, String appenderType, Object... config) {return getLogger(clazz.getName(), appenderType, config);}private static Logger createLogger(String name, String appenderType, Object... config) {LogAppender appender = createAppender(appenderType, config);// 可以根据需要选择不同类型的Loggerreturn new LevelLogger(name, appender);}private static LogAppender createAppender(String appenderType, Object... config) {switch (appenderType.toLowerCase()) {case "console":return new ConsoleLogAppender();case "file":if (config.length > 0 && config[0] instanceof String) {return new FileLogAppender((String) config[0]);} else {return new FileLogAppender("application.log");}case "database":if (config.length >= 2 && config[0] instanceof DataSource && config[1] instanceof String) {return new DatabaseLogAppender((DataSource) config[0], (String) config[1]);} else {throw new IllegalArgumentException("数据库日志需要DataSource和表名参数");}default:return new ConsoleLogAppender();}}
}// 客户端使用示例
public class LoggerDemo {public static void main(String[] args) {// 开发环境使用控制台日志Logger consoleLogger = LoggerFactory.getLogger("UserService", "console");consoleLogger.info("用户服务启动");consoleLogger.debug("调试信息");consoleLogger.error("发生错误", new RuntimeException("测试异常"));// 生产环境使用文件日志Logger fileLogger = LoggerFactory.getLogger("OrderService", "file", "order-service.log");fileLogger.info("订单服务启动");fileLogger.warn("订单处理警告");// 审计日志使用数据库存储DataSource dataSource = ... // 获取数据源Logger dbLogger = LoggerFactory.getLogger("AuditService", "database", dataSource, "audit_log");dbLogger.info("用户登录审计");// 测试日志级别控制LevelLogger levelLogger = (LevelLogger) LoggerFactory.getLogger("TestService", "console");levelLogger.setLevel(LevelLogger.LogLevel.WARN);levelLogger.debug("这条DEBUG日志不会输出");levelLogger.info("这条INFO日志不会输出");levelLogger.warn("这条WARN日志会输出");levelLogger.error("这条ERROR日志会输出");}
}
http://www.sczhlp.com/news/91870/

相关文章:

  • 诸暨营销型网站设计响应式网站好还是自适应网站好
  • 海门城乡建设管理局网站安卓系统软件开发培训机构
  • 最权威的品牌排行榜网站pc网站建设哪个好
  • linux环境docker离线镜像elasticsearch-7.17.3镜像资源
  • 丹阳企业网站九江网站建设制作
  • 电子商务网站建设调研报告中国石油工程建设公司
  • 多用户商城网站开发互联网站管理工作细则
  • 个人网站 虚拟主机价格淘宝客官网
  • 免费网站建设行情网站服务器能更换吗
  • 百度网站首页的设计理念电子商务网站开发相关技术
  • 沈阳企业网站建设胶州网站优化
  • 手机小说网站源码网站开发怎么销售
  • 律师事务所网站设计方案郑州聚商网络科技有限公司
  • 网站修改title百度推广网站怎么做
  • 成都定制网站设网站登录页面html模板
  • 设计类专业网站公司注册地址异常
  • 影响力网站建设邯郸本地网站
  • 企业网站模板趋势苏州建设工程网
  • 温州网站设计工作室网站宣传推广平台
  • 网站开发软件 d湖北电商的网络推广
  • 网站被人做跳转了92号汽油价格最新
  • 门业网站 模板寻找客户的12种方法
  • 上海做网站公宁乡市建设局网站
  • 网站诊断分析报告模板及优化执行方案.doc想学程序员去哪里学
  • 北京网络网站建设公司天津网页制作网页报价
  • 企业网站租服务器烟台城乡建设局官方信息网站
  • android最新版本百度seo流量
  • 做的网站图片不显示学校网站建设意义
  • 网站icp备案 去哪房地产信息网新楼盘
  • 做彩票网站广东深圳罗湖直客三部