自学内容网 自学内容网

Bridge(桥接)

1)意图

将抽象部分与其实现部分分离,使它们都可以独立地变化。

2)结构

桥接模式的结构如图 7-32 所示。
在这里插入图片描述
其中:

  • Abstraction 定义抽象类的接口,维护一个指向 Implementor 类型对象的指针。
  • RefinedAbstraction 扩充由Abstraction 定义的接口。
  • Implementor 定义实现类的接口,该接口不一定要与 Abstraction 的接口完全一致;事实上这两个接口可以完全不同。一般来说,Implementor 接口仅提供基本操作,而Abstraction 定义了基于这些基本操作的较高层次的操作。
  • Concretelmplementor 实现 Implementor 接口并定义它的具体实现。

3)适用性

Bridge 模式适用于:

  • 不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如,这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这是 Bridge 模式使得开发者可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译。
  • (C++)想对客户完全隐藏抽象的实现部分。
  • 有许多类要生成的类层次结构。
  • 想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。

4 应用举例

1. 数据访问层(DAO)与数据库实现

在Web应用中,数据访问层(DAO)通常需要与不同的数据库进行交互。使用桥接模式可以将数据访问的抽象与具体的数据库实现分离,从而提高代码的灵活性和可维护性。

  1. 定义数据访问接口
// 数据访问接口
public interface DataAccess {
    void save(Object entity);
    Object findById(String id);
}
  1. 实现具体的数据访问
// MySQL数据访问实现
public class MySQLDataAccess implements DataAccess {
    @Override
    public void save(Object entity) {
        System.out.println("Saving to MySQL: " + entity);
    }

    @Override
    public Object findById(String id) {
        System.out.println("Finding by ID in MySQL: " + id);
        return new Object();
    }
}

// PostgreSQL数据访问实现
public class PostgreSQLDataAccess implements DataAccess {
    @Override
    public void save(Object entity) {
        System.out.println("Saving to PostgreSQL: " + entity);
    }

    @Override
    public Object findById(String id) {
        System.out.println("Finding by ID in PostgreSQL: " + id);
        return new Object();
    }
}
  1. 定义抽象的DAO
// 抽象的DAO
public abstract class AbstractDAO {
    protected DataAccess dataAccess;

    public AbstractDAO(DataAccess dataAccess) {
        this.dataAccess = dataAccess;
    }

    public abstract void saveEntity(Object entity);
    public abstract Object findEntityById(String id);
}
  1. 实现具体的DAO
// 用户DAO
public class UserDAO extends AbstractDAO {
    public UserDAO(DataAccess dataAccess) {
        super(dataAccess);
    }

    @Override
    public void saveEntity(Object entity) {
        dataAccess.save(entity);
    }

    @Override
    public Object findEntityById(String id) {
        return dataAccess.findById(id);
    }
}
  1. 测试桥接模式
public class Main {
    public static void main(String[] args) {
        DataAccess mysqlDataAccess = new MySQLDataAccess();
        DataAccess postgresqlDataAccess = new PostgreSQLDataAccess();

        UserDAO userDAO1 = new UserDAO(mysqlDataAccess);
        userDAO1.saveEntity(new Object());
        userDAO1.findEntityById("123");

        UserDAO userDAO2 = new UserDAO(postgresqlDataAccess);
        userDAO2.saveEntity(new Object());
        userDAO2.findEntityById("456");
    }
}

2. 日志记录与日志实现

在Web应用中,日志记录是一个常见的功能。使用桥接模式可以将日志记录的抽象与具体的日志实现分离,从而支持多种日志记录方式(如文件日志、数据库日志、网络日志等)。

  1. 定义日志记录接口
// 日志记录接口
public interface Logger {
    void log(String message);
}
  1. 实现具体的日志记录
// 文件日志记录实现
public class FileLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("Logging to file: " + message);
    }
}

// 数据库日志记录实现
public class DatabaseLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("Logging to database: " + message);
    }
}
  1. 定义抽象的日志记录器
// 抽象的日志记录器
public abstract class AbstractLogger {
    protected Logger logger;

    public AbstractLogger(Logger logger) {
        this.logger = logger;
    }

    public abstract void logMessage(String message);
}
  1. 实现具体的日志记录器
// 应用日志记录器
public class ApplicationLogger extends AbstractLogger {
    public ApplicationLogger(Logger logger) {
        super(logger);
    }

    @Override
    public void logMessage(String message) {
        logger.log(message);
    }
}
  1. 测试桥接模式
public class Main {
    public static void main(String[] args) {
        Logger fileLogger = new FileLogger();
        Logger databaseLogger = new DatabaseLogger();

        ApplicationLogger appLogger1 = new ApplicationLogger(fileLogger);
        appLogger1.logMessage("This is a file log message.");

        ApplicationLogger appLogger2 = new ApplicationLogger(databaseLogger);
        appLogger2.logMessage("This is a database log message.");
    }
}

3. 用户界面与渲染实现

在Web应用中,用户界面的渲染可能需要支持多种不同的前端技术(如HTML、JSON、XML等)。使用桥接模式可以将用户界面的抽象与具体的渲染实现分离,从而支持多种渲染方式。

  1. 定义渲染接口
// 渲染接口
public interface Renderer {
    void render(Object data);
}
  1. 实现具体的渲染
// HTML渲染实现
public class HtmlRenderer implements Renderer {
    @Override
    public void render(Object data) {
        System.out.println("Rendering as HTML: " + data);
    }
}

// JSON渲染实现
public class JsonRenderer implements Renderer {
    @Override
    public void render(Object data) {
        System.out.println("Rendering as JSON: " + data);
    }
}
  1. 定义抽象的用户界面
// 抽象的用户界面
public abstract class AbstractUI {
    protected Renderer renderer;

    public AbstractUI(Renderer renderer) {
        this.renderer = renderer;
    }

    public abstract void display(Object data);
}
  1. 实现具体的用户界面
// 用户界面
public class UserInterface extends AbstractUI {
    public UserInterface(Renderer renderer) {
        super(renderer);
    }

    @Override
    public void display(Object data) {
        renderer.render(data);
    }
}
  1. 测试桥接模式
public class Main {
    public static void main(String[] args) {
        Renderer htmlRenderer = new HtmlRenderer();
        Renderer jsonRenderer = new JsonRenderer();

        UserInterface ui1 = new UserInterface(htmlRenderer);
        ui1.display(new Object());

        UserInterface ui2 = new UserInterface(jsonRenderer);
        ui2.display(new Object());
    }
}

桥接模式在Web开发中非常有用,特别是在需要支持多种实现方式的场景下。通过将抽象部分与实现部分分离,桥接模式可以提高代码的灵活性和可维护性,减少类的膨胀,使系统更加模块化和易于扩展。上述三个案例分别展示了在数据访问、日志记录和用户界面渲染中的应用,希望这些示例能帮助你更好地理解和应用桥接模式。


原文地址:https://blog.csdn.net/QQ657205470/article/details/143576319

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!