zoukankan      html  css  js  c++  java
  • 设计模式学习笔记(五、结构型-适配器模式)

    目录:

    • 什么是适配器模式
    • 为什么要有适配器模式
    • 如何实现适配器模式
    • 适配器模式的使用场景
    • 代理、桥接、装饰、适配器区别

    什么是适配器模式

    从语义上就能很明白的看出适配器模式是什么,它其实就是用来做适配的,把不兼容的接口转成成兼容的接口。

    在生活中有一种东西非常贴合适配器模式,就是读卡器,它是用来兼容内存卡和USB接口。

    为什么要有适配器模式

    把不兼容的接口转成成兼容的接口

    如何实现适配器模式

    适配器的实现方式有两种:

    1、类适配器:通过继承实现

    1 public interface IAdapter {
    2 
    3     void func1();
    4     void func2();
    5     void func3();
    6 }
     1 public class Adaptee {
     2 
     3     public void f1() {
     4     }
     5 
     6     public void f2() {
     7     }
     8 
     9     public void func3() {
    10     }
    11 }
     1 public class Adaptor extends Adaptee implements IAdapter {
     2     
     3     @Override
     4     public void func1() {
     5         super.f1();
     6     }
     7 
     8     @Override
     9     public void func2() {
    10         // 重新实现fund2的逻辑
    11     }
    12 
    13     // 这里fc()不需要实现,直接继承自Adaptee,这是跟对象适配器最大的不同点
    14 }

    2、对象适配器:通过组合实现

    1 public interface IAdapter {
    2 
    3     void func1();
    4     void func2();
    5     void func3();
    6 }
     1 public class Adaptee {
     2 
     3     public void f1() {
     4     }
     5 
     6     public void f2() {
     7     }
     8 
     9     public void func3() {
    10     }
    11 }
     1 public class Adaptor implements IAdapter {
     2 
     3     private Adaptee adaptee;
     4 
     5     public Adaptor(Adaptee adaptee) {
     6         this.adaptee = adaptee;
     7     }
     8 
     9     @Override
    10     public void func1() {
    11         // 委托给adaptee实现
    12         adaptee.f1();
    13     }
    14 
    15     @Override
    16     public void func2() {
    17         // 重写func2
    18     }
    19 
    20     @Override
    21     public void func3() {
    22         // 委托给adaptee实现
    23         adaptee.func3();
    24     }
    25 }

    你这两种方式该如何选择呢,一看接口数量,二看契合度。

    • 如果接口数量不是很多,两个都可以。
    • 如果接口数量较多,且Adaptee与IAdapter中的接口相似度高(契合度),推荐使用类适配器的方式,这样Adaptor的代码更简洁。
    • 如果接口数量较多,但契合度不高,则推荐使用对适配器,因为基于组合的方式更加灵活。

    适配器模式的使用场景

    一般来说,适配器模式可以看作一种“补偿模式”,用来补救设计上的缺陷。

    应用这种模式算是“无奈之举”。如果在设计初期,我们就能协调规避接口不兼容的问题,那这种模式就没有应用的机会了。

    ———————————————————————————————————————————————————————

    1、封装有缺陷的接口设计

    比如外部系统在设计上有缺陷(比如有大量静态方法、一个函数参数过多),而我们又不能改,那我们可以对其进行二次封装。———————————————————————————————————————————————————————

    2、统一多个类的接口设计

    假如你要对用户敏感词过滤,为了增加用户粘性,我们引入了多款第三方敏感词过滤系统,尽量的过滤多条敏感词。

    但是,每个系统提供的过滤接口都是不同的。这就意味着我们没法复用一套逻辑来调用各个系统。

    这个时候,我们就可以使用适配器模式,将所有系统的接口适配为统一的接口定义,这样我们可以复用调用敏感词过滤的代码。

     1 /**
     2  * A系统敏感词过滤
     3  *
     4  * @author zhoude
     5  * @date 2020/4/11 13:00
     6  */
     7 public class AThirdFilter {
     8 
     9     /**
    10      * text是原始文本,函数输出用***替换敏感词之后的文本
    11      */
    12     public String filterSexyWords(String text) {
    13         // 伪实现
    14         return "***";
    15     }
    16 
    17     public String filterPoliticalWords(String text) {
    18         // 伪实现
    19         return "+++";
    20     }
    21 }
     1 /**
     2  * B系统敏感词过滤
     3  *
     4  * @author zhoude
     5  * @date 2020/4/11 13:00
     6  */
     7 public class BThirdFilter {
     8 
     9     public String filter(String text) {
    10         // 伪实现
    11         return "***";
    12     }
    13 }
     1 /**
     2  * C系统敏感词过滤
     3  *
     4  * @author zhoude
     5  * @date 2020/4/11 13:00
     6  */
     7 public class CThirdFilter {
     8 
     9     public String filter(String text, String mask) {
    10         // 伪实现
    11         return mask;
    12     }
    13 }
     1 public class Test {
     2 
     3     private AThirdFilter aThirdFilter = new AThirdFilter();
     4     private BThirdFilter bThirdFilter = new BThirdFilter();
     5     private CThirdFilter cThirdFilter = new CThirdFilter();
     6 
     7     public String filter(String text) {
     8         // 未使用适配器模式之前的代码:代码的可测试性、扩展性不好
     9         String result = aThirdFilter.filterPoliticalWords(text);
    10         result = aThirdFilter.filterSexyWords(result);
    11         result = bThirdFilter.filter(result);
    12         result = cThirdFilter.filter(result, "***");
    13         return result;
    14     }
    15 }

    使用之后:

    1 public interface IThirdFilter {
    2 
    3     String filter(String text);
    4 }
     1 public class AThirdFilterImpl implements IThirdFilter {
     2 
     3     private AThirdFilter filter;
     4 
     5     public AThirdFilterImpl(AThirdFilter aThirdFilter) {
     6         this.filter = aThirdFilter;
     7     }
     8 
     9     @Override
    10     public String filter(String text) {
    11         String result = filter.filterPoliticalWords(text);
    12         result = filter.filterSexyWords(result);
    13         return result;
    14     }
    15 }
     1 public class BThirdFilterImpl implements IThirdFilter {
     2 
     3     private BThirdFilter filter;
     4 
     5     public BThirdFilterImpl(BThirdFilter aThirdFilter) {
     6         this.filter = aThirdFilter;
     7     }
     8 
     9     @Override
    10     public String filter(String text) {
    11         return filter.filter(text);
    12     }
    13 }
     1 public class CThirdFilterImpl implements IThirdFilter {
     2 
     3     private CThirdFilter filter;
     4 
     5     public CThirdFilterImpl(CThirdFilter aThirdFilter) {
     6         this.filter = aThirdFilter;
     7     }
     8 
     9     @Override
    10     public String filter(String text) {
    11         return filter.filter(text, "***");
    12     }
    13 }
     1 public class Test {
     2 
     3     private List<IThirdFilter> filterList = new ArrayList<>();
     4 
     5     public void addFilter(IThirdFilter filter) {
     6         filterList.add(filter);
     7     }
     8 
     9     public String filter(String text) {
    10         String result = text;
    11         for (IThirdFilter filter : filterList) {
    12             result = filter.filter(result);
    13         }
    14         return result;
    15     }
    16 }

    ———————————————————————————————————————————————————————

    3、替换依赖的外部系统:当我们把项目中依赖的一个外部系统替换为另一个外部系统的时候,利用适配器模式,可以减少对代码的改动。

    ———————————————————————————————————————————————————————

    4、适配不同的数据格式:如Java 中的 Arrays.asList()。

    代理、桥接、装饰、适配器区别

    • 代理模式:代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同。
    • 桥接模式:桥接模式的目的是将接口部分和实现部分分离,从而让它们可以较为容易、也相对独立地加以改变。
    • 装饰器模式:装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用。
    • 适配器模式:适配器模式是一种事后的补救策略。适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口。
  • 相关阅读:
    如何实现九宫格布局-----源码如下
    查询出的数据记录字段要与实体类中的属性名一致
    2016/12/14---- C3P0
    Spring的数据库操作---- Spring框架对JDBC的整合 ---- 初始化JdbcTemplate对象
    Spring的数据库操作---- Spring框架对JDBC的整合---- 初始化连接池数据源对象
    Spring的数据库操作---- Spring框架对JDBC的整合---- Spring的数据库操作
    Spring的数据库操作---- Spring框架对JDBC的整合---- spring集成jdbc概述
    Spring的AOP机制---- AOP的注解配置---- AOP的注解配置
    Spring的AOP机制---- 切入点表达式---- 切入点表达式
    Spring的AOP机制---- AOP环绕通知---- AOP环绕通知
  • 原文地址:https://www.cnblogs.com/bzfsdr/p/12679127.html
Copyright © 2011-2022 走看看