本文通过老王和小王买车介绍了设计模式中结构设计的桥接模式,然后讲解了设计模式的概念和代码实现。为了加深理解,会在JDBC的应用中讲解适配器设计模式,最后说一下桥接模式和适配器模式的总结。读者可以拉取完整代码在本地学习,测试通过后将代码上传至码云。1.导致问题老王和小王去奔驰4S店买车。奔驰4S店拥有多种品牌和型号。老王要试驾奔驰E,小王要试驾奔驰G,想体验各种颜色,让店员犯难了。两对的组合很多,4S店根本装不下。无奈,店员求助店长,店长记下:将奔驰E和G的品牌进行抽象,颜色也进行抽象,用品牌和颜色的组合代替继承关系,减少颜色和品牌之间的耦合,减少汽车数量。只要两套就够了。果然,经理不愧是经理。经理说的其实是桥接模式。该模式涉及充当桥梁的接口,使实体类的功能独立于接口实现类。两种类型的类都可以在结构上相互独立地进行更改。2.概念和使用先看一些概念:Bridge用于解耦抽象和实现,让两者可以独立变化。这类设计模式属于结构型模式,通过在抽象和实现之间提供一个桥接结构来实现两者的解耦。该模式涉及的角色应该有四种:①Implementor:定义实现角色的接口,可用于扩展抽象角色。比如抽象出来的奔驰品牌benz可以扩展为benzEbenzG②ConcreteImplementor:实现类的具体实现,比如各种奔驰品牌③抽象(Abstraction)角色:定义一个抽象类,它引用了实现角色(要组合),如汽车产品④扩展抽象(RefinedAbstraction)角色:抽象角色子类实现父类的方法,通过组合关系调用已实现角色中的业务方法,如具体的奔驰产品,红色奔驰,白色奔驰。根据这个模型的定义,我们把奔驰的品牌抽象出来,然后每个品牌都有自己在汽车的每一种颜色的实现中,结合汽车的品牌。在客户端中,每个相机类型和相机品牌都可以成对组合。下面看具体的代码实现:实现类接口:/***Mercedes-Benzbrandclass*@authortcy*@Date05-08-2022*/publicinterfaceBenzBrand{voidshowInfo();}具体实现角色1:/***@authortcy*@Date05-08-2022*/publicclassBenzEimplementsBenzBrand{@OverridepublicvoidshowInfo(){System.out.print("【BenzE】颜色是:");}}具体实现角色2:/***@authortcy*@Date05-08-2022*/publicclassBenzGimplementsBenzBrand{@OverridepublicvoidshowInfo(){System.out.print("[BenzG]颜色是:");}}Abstractrole:/***AbstractBenzclass*@authortcy*@Date05-08-2022*/publicabstractclassBenz{//将品牌组合成受保护的BenzBrandbenzBrand;公共奔驰(BenzBrandbenzBrand){这个.benzBrand=benzBrand;}publicvoidshowInfo(){benzBrand.showInfo();}}扩展抽象1:/***@authortcy*@Date05-08-2022*/publicclassBlackBenzextendsBenz{publicBlackBenz(BenzBrandbenzBrand){super(benzBrand);}@OverridepublicvoidshowInfo(){super.show信息();System.out.println("黑...");}}扩展抽象2:/***@authortcy*@Date05-08-2022*/publicclassRedBenzextendsBenz{publicReBenz(BenzBrandbenzBrand){super(benzBrand);}@OverridepublicvoidshowInfo(){super.showInfo();System.out.println("红...");}}客户端调用:/***@authortcy*@Date05-08-2022*/publicclassClient{publicstaticvoidmain(String[]args){//BlackBenzEBenzbenz1=newBlackBenz(newBenzE());benz1.showInfo();//黑色奔驰GBenzbenz2=newBlackBenz(newBenzG());benz2.showInfo();//红色奔驰EBenzbenz3=newRedBenz(newBenzE());benz3.showInfo();//红色奔驰GBenzbenz4=newRedBenz(newBenzG());benz4.showInfo();}【奔驰E】颜色为:黑色...【奔驰G】颜色为:黑色...【奔驰E】颜色为:红色...【奔驰G】颜色为:红色...在这方式,即使老王提出新颜色或新模型,也只需要添加相应的具体实现角色或扩展抽象角色即可。顾名思义,桥接模式就像是一座桥,可以用来连接两个不同的地方。两地自由发展,中间的贸易通过一座桥梁相连。这种方法的缺点也很明显。汽车可以快速建立车型和颜色两个维度。在实际业务开发中,识别系统的两个独立变化的维度并不容易。不难看出,列举的例子有点太过牵强了,在现实世界中是绝对不会发生的。为了加深理解,找了很多JDK或者Spirng等各种框架中桥接模式的应用,才发现桥接模式。Jdbc中的应用程序。3、应用我们都知道Java可以通过JDBC完成对关系型数据库的SQL操作。我们在连接数据数据库的时候,肯定接触过Drivers。连接MySQL和Oracle的驱动是不一样的,都是接口类。.我们来看看MySQL中实现的Driver类。publicclassDriverextendsNonRegisteringDriverimplementsjava.sql.Driver{publicDriver()throwsSQLException{}static{try{DriverManager.registerDriver(newDriver());}catch(SQLExceptionvar1){thrownewRuntimeException("无法注册驱动程序!");}}}这个类其实有两个功能,一个是调用DriverManager中的registerDriver方法注册驱动,另一个是驱动注册完成后调用DriverManager中的getConnection方法。我们看DriverManager的完整代码:如果(用户!=null){info.put(“用户”,用户);}if(password!=null){info.put("密码",密码);}return(getConnection(url,info,Reflection.getCallerClass()));}privatestaticConnectiongetConnection(Stringurl,java.util.Propertiesinfo,Class>caller)throwsSQLException{/**当callerCl为null时,我们应该检查应用程序的*(间接调用此类)*类加载器,以便可以从这里加载rt.jar*之外的JDBC驱动程序类。*/ClassLoadercallerCL=caller!=null?调用者.getClassLoader():null;synchronized(DriverManager.class){//同步加载正确的cl装载机。if(callerCL==null){callerCL=Thread.currentThread().getContextClassLoader();}}if(url==null){thrownewSQLException("Theurlcannotbenull","08001");}println("DriverManager.getConnection(\""+url+"\")");//遍历尝试建立连接的已加载注册驱动程序。//记住第一个引发的异常,这样我们就可以重新引发它。SQLException原因=null;for(DriverInfoaDriver:registeredDrivers){//如果调用者没有加载驱动程序的权限,则//跳过它。if(isDriverAllowed(aDriver.driver,callerCL)){try{println("trying"+aDriver.driver.getClass().getName());连接con=aDriver.driver.connect(url,info);if(con!=null){//成功!println("getConnection返回"+aDriver.driver.getClass().getName());返回(con);}}catch(SQLExceptionex){if(reason==null){reason=ex;}}}else{println("跳过:"+aDriver.getClass().getName());}}//如果我们到了这里,没有人可以连接。if(reason!=null){println("getConnectionfailed:"+reason);抛出原因;}println("getConnection:没有找到适合"+url的驱动程序);thrownewSQLException("Nosuitabledriverfoundfor"+url,"08001");}}}Java中通过Connection为各个数据库提供了这里的操作接口,这里的Connection可以看成是一个抽象类。可以说我们操作不同数据库的方法都是一样的,只是MySQL有自己的ConnectionImpl类,Oracle也有相应的实现类。在这里,Driver和Connection通过DriverManager类桥接。这种桥接模式与我们在上面可以清楚看到的角色不同。4.总结桥接模式简单易懂。相信仔细看过例子的同学应该能看懂,但这并不代表你已经掌握了设计模式。我们在使用JDBC的时候,肯定有很多同学看不出来这是桥接模式。纸上谈兵不易理解,“构思”了一些例子来说明桥接模式,每个角色都清晰直观。看完这样的代码,你可以学习桥接模式,但你很可能不会在实践中使用它。最好的方法是举出真实项目的例子。但是这个难度真的很大。一旦进入真实项目,会遇到很多细节问题,影响对模型的理解,而真实项目有一定的业务环境。了解和学习设计模式是一回事,在实际开发中选择最佳的设计模式又是另一回事。这不仅需要对每个设计模式有很好的理解,还需要对业务有理解,对代码概念有把握。控制。建议读者参考软件设计七大原则仔细阅读前面的文章,认真理解。创建型设计模式:1.设计模式的工厂方法和抽象工厂2.设计模式的单例和原型3.设计模式的建造者模式结构型设计模式:4.设计模式的代理模式5.设计模式模型的适配器
