This is the 24th day of my participation in Gwen Challenge

Design patterns

The bridge model

The implementation and abstraction are placed in two different class levels, so that the two levels can be changed independently, that is, abstraction and implementation decouple, so that they can be changed independently

If we now have cars and trains, the means of power are electricity and oil. The bridge mode is as follows

Provides the VehicleType interface

package com.wangscaler.bridge;

/ * * *@author wangscaler
 * @date 2021.06.24 16:48
 */
public interface VehicleType {
    void run(a);
}
Copy the code

For Car to implement

package com.wangscaler.bridge;

/ * * *@author wangscaler
 * @date 2021.06.24 16:48
 */
public class Car implements VehicleType {
    @Override
    public void run(a) {
        System.out.println("The cars are moving."); }}Copy the code

Train to achieve

package com.wangscaler.bridge;

/ * * *@author wangscaler
 * @date 2021.06.24 16:48
 */
public class Train implements VehicleType {
    @Override
    public void run(a) {
        System.out.println("The train is moving."); }}Copy the code

The bridge in the middle is the abstract class Vehicle

package com.wangscaler.bridge;

/ * * *@author wangscaler
 * @date 2021.06.24 16:48
 */
public abstract class Vehicle {
    private VehicleType vehicleType;

    public Vehicle(VehicleType vehicleType) {
        this.vehicleType = vehicleType;
    }

    protected void run(a) {
        this.vehicleType.run(); }}Copy the code

ElectricVehicle obtains super.run() from the implementation class of the interface by inheriting the Vehicle bridge;

package com.wangscaler.bridge;

/ * * *@author wangscaler
 * @date 2021.06.24 16:48
 */
public class ElectricVehicle extends Vehicle {
    public ElectricVehicle(VehicleType vehicleType) {
        super(vehicleType);
    }

    @Override
    protected void run(a) {
        System.out.println("Provide electricity");
        super.run(); }}Copy the code

In the same way, the OilVehicle obtains super.run() in the implementation class of the interface by inheriting the Vehicle bridge;

package com.wangscaler.bridge;

/ * * *@author wangscaler
 * @date 2021.06.24 16:48
 */
public class OilVehicle extends Vehicle {
    public OilVehicle(VehicleType vehicleType) {
        super(vehicleType);
    }

    @Override
    protected void run(a) {
        System.out.println("Provide oil");
        super.run(); }}Copy the code

main

package com.wangscaler.bridge;

/ * * *@author wangscaler
 * @date 2021.06.24 16:48
 */

public class Bridge {
    public static void main(String[] args) {
        ElectricVehicle electricVehicle = new ElectricVehicle(newTrain()); electricVehicle.run(); }}Copy the code

When we added the hybrid, we just added the OilElectricVehicle

package com.wangscaler.bridge;

/ * * *@author wangscaler
 * @date 2021.06.24 16:48
 */
public class OilElectricVehicle extends Vehicle {
    public OilElectricVehicle(VehicleType vehicleType) {
        super(vehicleType);
    }

    @Override
    protected void run(a) {
        System.out.println("A mixture of oil and electricity.");
        super.run(); }}Copy the code

Can be implemented.

Source bridge mode

Driver interface in JDBC

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.mysql.cj.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver(a) throws SQLException {}static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!"); }}}Copy the code

Java.sql.Driver is a bridge interface. The above code is the Mysql Driver implementation class of the Driver, and of course the Orcale Driver implements this interface

The implementation class registers the Driver through the registerDriver of DriverManager and adds the Driver to the registeredDrivers.

When we load the Mysql driver, the connection will be loaded according to the driver used when getConnection is called by DriverManager

public class DriverManager {
   private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
    public static synchronized void registerDriver(java.sql.Driver driver)
        throws SQLException {

        registerDriver(driver, null);
    }
    
    @CallerSensitive
    public static Connection getConnection(String url, java.util.Properties info) throws SQLException {

        return (getConnection(url, info, Reflection.getCallerClass()));
    }
	public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da)
        throws SQLException {

        /* Register the driver if it has not already been added to our list */
        if(driver ! =null) {
            registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
        } else {
            // This is for compatibility with the original DriverManager
            throw new NullPointerException();
        }

        println("registerDriver: " + driver);

    }

    @CallerSensitive
    public static Connection getConnection(String url, String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();

        if(user ! =null) {
            info.put("user", user);
        }
        if(password ! =null) {
            info.put("password", password);
        }

        return (getConnection(url, info, Reflection.getCallerClass()));
    }


    @CallerSensitive
    public static Connection getConnection(String url)
        throws SQLException {

        java.util.Properties info = new java.util.Properties();
        return (getConnection(url, info, Reflection.getCallerClass()));
    }
     private static Connection getConnection( String url, java.util.Properties info, Class
        caller) throws SQLException {
        /* * When callerCl is null, we should check the application's * (which is invoking this class indirectly) * classloader, so that the JDBC driver class outside rt.jar * can be loaded from here. */ClassLoader callerCL = caller ! =null ? caller.getClassLoader() : null;
        synchronized(DriverManager.class) {
            // synchronize loading of the correct classloader.
            if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); }}if(url == null) {
            throw new SQLException("The url cannot be null"."08001");
        }

        println("DriverManager.getConnection(\"" + url + "\")");

        // Walk through the loaded registeredDrivers attempting to make a connection.
        // Remember the first exception that gets raised so we can reraise it.
        SQLException reason = null;

        for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    println(" trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if(con ! =null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return(con); }}catch (SQLException ex) {
                    if (reason == null) { reason = ex; }}}else {
                println(" skipping: "+ aDriver.getClass().getName()); }}// if we got here nobody could connect.
        if(reason ! =null)    {
            println("getConnection failed: " + reason);
            throw reason;
        }

        println("getConnection: no suitable driver found for "+ url);
        throw new SQLException("No suitable driver found for "+ url, "08001"); }}Copy the code

Mysql Driver, for example, inherits NonRegisteringDriver and implements connect

public class NonRegisteringDriver implements Driver {

    public Connection connect(String url, Properties info) throws SQLException {
        try {
            try {
                if(! ConnectionUrl.acceptsUrl(url)) {return null;
                } else {
                    ConnectionUrl conStr = ConnectionUrl.getConnectionUrlInstance(url, info);
                    switch(conStr.getType()) {
                    case SINGLE_CONNECTION:
                        return ConnectionImpl.getInstance(conStr.getMainHost());
                    case FAILOVER_CONNECTION:
                    case FAILOVER_DNS_SRV_CONNECTION:
                        return FailoverConnectionProxy.createProxyInstance(conStr);
                    case LOADBALANCE_CONNECTION:
                    case LOADBALANCE_DNS_SRV_CONNECTION:
                        return LoadBalancedConnectionProxy.createProxyInstance(conStr);
                    case REPLICATION_CONNECTION:
                    case REPLICATION_DNS_SRV_CONNECTION:
                        return ReplicationConnectionProxy.createProxyInstance(conStr);
                    default:
                        return null; }}}catch (UnsupportedConnectionStringException var5) {
                return null;
            } catch (CJException var6) {
                throw (UnableToConnectException)ExceptionFactory.createException(UnableToConnectException.class, Messages.getString("NonRegisteringDriver.17".newObject[]{var6.toString()}), var6); }}catch (CJException var7) {
            throwSQLExceptionsMapping.translateException(var7); }}}Copy the code

So we use Mysql driver, call getConnection is to get the Mysql connection.

conclusion

1. The biggest characteristic of bridge mode is the separation of abstraction and implementation, which greatly increases the flexibility of the system and thus produces structured system.

2, suitable for those systems that do not want inheritance or multi-level inheritance to lead to a sharp increase in the number of system classes; A class has two dimensions that change independently, and both dimensions need to be extended.

3, extend any dimension, only need to increase without modification. In line with the open and close principle.

The resources

  • JAVA Design Pattern