北京网站建设汉邦,湛江建设企业网站,做外贸生意哪个网站好,注册一家公司最低需要多少钱文章目录 介绍生活中的案例基础介绍工作原理分类应用场景 案例类适配器模式例1介绍类图代码实现优缺点分析 例2类图代码实现 对象适配器模式#xff08;常用方式#xff09;例1介绍类图代码实现优缺点分析 例2代码实现 接口适配器模式介绍类图代码实现 登场角色类图类适配器模… 文章目录 介绍生活中的案例基础介绍工作原理分类应用场景 案例类适配器模式例1介绍类图代码实现优缺点分析 例2类图代码实现 对象适配器模式常用方式例1介绍类图代码实现优缺点分析 例2代码实现 接口适配器模式介绍类图代码实现 登场角色类图类适配器模式对象适配器模式 适配器模式在SpringMvc中的应用类图模拟实现分析 总结文章说明 介绍
生活中的案例
不同国家的插座不同出国旅游充电器不能直接使用可以通过使用多功能转换插头来辅助使用
基础介绍 适配器模式将某个类的接口转换成客户端期望的另一个接口表示主的目的是兼容性让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper) 适配器模式属于结构型模式没有产生什么新对象只是结构的一些调整让类与类之间可以协调工作
工作原理
将一个类的接口转换成另一种接口目的是让原本接口不兼容的类可以兼容从用户的角度看不到被适配者A调用B中间有个adpaterB属于被适配者是解耦的用户调用适配器转化出来的目标接口方法适配器再调用被适配者的相关接口方法用户收到反馈结果感觉只是和目标接口交互 分类
类适配器模式对象适配器模式接口适配器模式
应用场景
很多时候我们加入项目组的时候项目已经有一定的代码量了或者部分代码已经在生产环境上面使用了这些方法已经经过测试在我们开发新的项目时可以将这些类作为组件重复利用但是可能没办法直接调用需要我们使用适配器模式来让这些方法适配我们的现有项目。
疑问直接修改之前的类不就可以了吗为啥要使用适配器模式答之前的类都比较完善了如果在上面改乱了出了bug不好调试但是如果使用了适配器模式那出了bug就知道是适配器的问题。此外在Adapter模式中并非一定需要现成的代码。只要知道现有类的功能就可以编写出新的类。
适配器模式还能用于做新旧版本的兼容可以让新版本扮演Adaptee 角色旧版本扮演Target角色。接着编写一个扮演Adapter 角色的类让它使用新版本的类来实现旧版本的类中的方法。如下图 案例
类适配器模式
例1
介绍
Adapter类通过继承src类实现 dst 类接口完成src-dst的适配如生活中的小例子充电器本身相当于Adapter220V交流电相当于src(即被适配者)我们的dst(即目标)是5V直流电
类图 代码实现
【被适配的类】
package com.atguigu.adapter.classadapter;/*** 被适配的类*/
public class Voltage220V {/*** 输出220V的电压* return*/public int output220V() {int src 220;System.out.println(电压 src 伏);return src;}
}【适配接口】
package com.atguigu.adapter.classadapter;/*** 适配接口*/
public interface IVoltage5V {public int output5V();
}【适配器】
package com.atguigu.adapter.classadapter;/*** 适配器类 将220V转化为5V*/
public class VoltageAdapter extends Voltage220V implements IVoltage5V {Overridepublic int output5V() {//获取到220V电压int srcV output220V();//转成 5v降压int dstV srcV / 44 ;return dstV;}}【手机类】
package com.atguigu.adapter.classadapter;public class Phone {/*** 手机充电方法* param iVoltage5V*/public void charging(IVoltage5V iVoltage5V) {if(iVoltage5V.output5V() 5) {System.out.println(电压为5V, 可以充电~~);} else if (iVoltage5V.output5V() 5) {System.out.println(电压过高, 不能充电~~);}}
}【客户端用户给手机充电】
package com.atguigu.adapter.classadapter;public class Client {public static void main(String[] args) {System.out.println( 类适配器模式 );Phone phone new Phone();phone.charging(new VoltageAdapter());}}【运行】 类适配器模式
电压220伏
电压为5V, 可以充电~~Process finished with exit code 0优缺点分析
【优点】
由于其继承了src类所以它可以根据需求重写src类的方法使得Adapter的灵活性增强了
【缺点】
Java是单继承机制所以类适配器需要继承src类这一点算是一个缺点之前的七大原则分析过使用继承不好因为这要求dst必须是接口有一定局限性src类的方法在Adapter中都会暴露出来也增加了使用的成本如果方法很多调用起来就麻烦了
例2
类图 代码实现
【src】
package com.atguigu.adapter.Sample1;public class Banner {private String string;public Banner(String string) {this.string string;}public void showWithParen() {System.out.println(( string ));}public void showWithAster() {System.out.println(* string *);}
}【dst】
package com.atguigu.adapter.Sample1;public interface Print {public abstract void printWeak();public abstract void printStrong();
}【适配器】
package com.atguigu.adapter.Sample1;public class PrintBanner extends Banner implements Print {public PrintBanner(String string) {super(string);}public void printWeak() {showWithParen();}public void printStrong() {showWithAster();}
}【客户端】
package com.atguigu.adapter.Sample1;public class Main {public static void main(String[] args) {Print p new PrintBanner(Hello);p.printWeak();p.printStrong();}
}【运行】
(Hello)
*Hello*Process finished with exit code 0【分析】
对Main类的代码而言Banner类、showWithParen方法和showWithAster 方法被完全隐藏起来了。这就好像笔记本电脑只要在直流12伏特电压下就能正常工作但它并不知道这12伏特的电压是由适配器将100伏特交流电压转换而成的。Main类并不知道PrintBanner类是如何实现的这样就可以在不用对Main类进行修改的情况下改变PrintBanner类的具体实现。
对象适配器模式常用方式
例1
介绍
基本思路和类的适配器模式相同只是将Adapter类作修改不是继承src类而是持有src类的实例聚合src类以解决兼容性的问题。 即:持有 src类实现 dst 类接口完成src-dst的适配根据“合成复用原则”在系统中尽量使用关联关系来替代继承关系对象适配器模式是适配器模式常用的一种
类图 代码实现
【适配器类】
package com.atguigu.adapter.objectadapter;/*** 适配器类*/
public class VoltageAdapter implements IVoltage5V {/*** 关联关系-聚合*/private Voltage220V voltage220V;/*** 通过构造器传入一个 Voltage220V 实例** param voltage220v*/public VoltageAdapter(Voltage220V voltage220v) {this.voltage220V voltage220v;}Overridepublic int output5V() {int dst 0;if (null ! voltage220V) {//获取220V 电压int src voltage220V.output220V();System.out.println(使用对象适配器进行适配~~);dst src / 44;System.out.println(适配完成输出的电压为 dst);}return dst;}}【客户端用户给手机充电】
package com.atguigu.adapter.objectadapter;public class Client {public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println( 对象适配器模式 );Phone phone new Phone();phone.charging(new VoltageAdapter(new Voltage220V()));}}其他类和类适配器模式的一致
优缺点分析
【优点】
对象适配器和类适配器其实算是同一种思想只不过实现方式不同。根据合成复用原则使用组合替代继承所以它解决了类适配器必须继承src的局限性问题也不再要求dst必须是接口使用成本更低更灵活
例2
代码实现
【dst】
package com.atguigu.adapter.Sample2;public abstract class Print {public abstract void printWeak();public abstract void printStrong();
}【适配器】
package com.atguigu.adapter.Sample2;public class PrintBanner extends Print {private Banner banner;public PrintBanner(String string) {this.banner new Banner(string);}public void printWeak() {banner.showWithParen();}public void printStrong() {banner.showWithAster();}
}其他两个类的和类适配器模式的例2的代码一致
接口适配器模式
介绍
一些书籍称为适配器模式(Default Adapter Pattern)或缺省适配器模式当不需要全部实现接口提供的方法时可先设计一个抽象类实现接口并为该接口中每个方法提供一个默认实现(空方法)那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求适用于不想使用一个接口所有的方法的情况 类图 代码实现
【接口】
package com.atguigu.adapter.interfaceadapter;public interface Interface4 {public void m1();public void m2();public void m3();public void m4();
}【抽象类适配器】
package com.atguigu.adapter.interfaceadapter;/*** 在AbsAdapter 我们将 Interface4 的方法进行默认实现空实现*/
public abstract class AbsAdapter implements Interface4 {Overridepublic void m1() {}Overridepublic void m2() {}Overridepublic void m3() {}Overridepublic void m4() {}
}【客户端重写抽象类的方法】
package com.atguigu.adapter.interfaceadapter;public class Client {public static void main(String[] args) {AbsAdapter absAdapter new AbsAdapter() {/*** 只需要去覆盖我们 需要使用 接口方法*/Overridepublic void m1() {System.out.println(使用了m1的方法);}};absAdapter.m1();}
}登场角色
Target(对象)负责定义所需的方法如需要能提供5v电压的方法Adaptee(被适配)该角色持有既定方法如有一个方法可以提供220v电压Adapter(适配)使用Adaptee角色的方法来满足Target角色的需求Client(请求者)负责使用 Target 角色所定义的方法来做事如使用5V电压给手机充电
类图
类适配器模式 对象适配器模式 适配器模式在SpringMvc中的应用
SpringMvc中的HandlerAdapter使用了适配器模式 类图 模拟实现
【Controller】
package com.atguigu.spring.springmvc;/*** 多种Controller实现*/
public interface Controller {}//-----------------针对不同的请求有多种不同的controller------------------------
class HttpController implements Controller {public void doHttpHandler() {System.out.println(http...);}
}class SimpleController implements Controller {public void doSimplerHandler() {System.out.println(simple...);}
}class AnnotationController implements Controller {public void doAnnotationHandler() {System.out.println(annotation...);}
}【适配器】
package com.atguigu.spring.springmvc;/*** 定义一个Adapter接口*/
public interface HandlerAdapter {public boolean supports(Object handler);public void handle(Object handler);
}//-------------------多种适配器类-------------------------class SimpleHandlerAdapter implements HandlerAdapter {public void handle(Object handler) {((SimpleController) handler).doSimplerHandler();}/*** 判断是否支持该handler* param handler* return*/public boolean supports(Object handler) {return (handler instanceof SimpleController);}}class HttpHandlerAdapter implements HandlerAdapter {public void handle(Object handler) {((HttpController) handler).doHttpHandler();}public boolean supports(Object handler) {return (handler instanceof HttpController);}}class AnnotationHandlerAdapter implements HandlerAdapter {public void handle(Object handler) {((AnnotationController) handler).doAnnotationHandler();}public boolean supports(Object handler) {return (handler instanceof AnnotationController);}}【servlet】
package com.atguigu.spring.springmvc;import java.util.ArrayList;
import java.util.List;public class DispatchServlet {/*** 组合所有适配器*/public static ListHandlerAdapter handlerAdapters new ArrayListHandlerAdapter();public DispatchServlet() {handlerAdapters.add(new AnnotationHandlerAdapter());handlerAdapters.add(new HttpHandlerAdapter());handlerAdapters.add(new SimpleHandlerAdapter());}public void doDispatch() {// 此处模拟SpringMVC从request取handler的对象// 适配器可以获取到希望的ControllerHttpController controller new HttpController();// AnnotationController controller new AnnotationController();//SimpleController controller new SimpleController();// 得到对应适配器HandlerAdapter adapter getHandler(controller);// 通过适配器执行对应的controller对应方法adapter.handle(controller);}/*** 根据controller返回对应的适配器* param controller* return*/public HandlerAdapter getHandler(Controller controller) {//遍历根据得到的controller(handler), 返回对应适配器for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(controller)) {return adapter;}}return null;}public static void main(String[] args) {new DispatchServlet().doDispatch(); // http...}}分析
适配器的价值controller变化了适配器也会跟着变化最终调用的方法也不同扩展Controller 时只需要增加一个适配器类就完成了SpringMVC的扩展了如果不使用适配器可以看到处理器的类型不同有多重实现方式那么调用方式就不是确定的如果需要直接调用Controller方法需要调用的时候就得不断是使用if else来进行判断是哪一种子类然后执行。那么如果后面要扩展Controller就得修改原来的代码这样违背了OCP原则 总结
类适配器以类给到在Adapter里就是将src当做类继承对象适配器: 以对象给到在Adapter里将src作为一个对象持有聚合接口适配器: 以接口给到在Adapter里将src作为一个接口实现Adapter模式最大的作用是将原本不兼容的接口融合在一起工作实际开发中实现起来不拘泥于上述三种经典形式
文章说明
本文章为本人学习尚硅谷的学习笔记文章中大部分内容来源于尚硅谷视频点击学习尚硅谷相关课程也有部分内容来自于自己的思考发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识如有侵权请联系删除最后对尚硅谷的优质课程表示感谢。本人还同步阅读《图解设计模式》书籍图解设计模式/(日)结城浩著;杨文轩译–北京:人民邮电出版社2017.1进而综合两者的内容让知识点更加全面