秒懂设计模式--学习笔记(10)【结构型-适配器模式】

07-19 1363阅读

目录

      • 9、适配器模式
          • 9.1 适配器模式
          • 9.2 翻译(举例)
          • 9.3 插头与插座(举例)
          • 9.4 通用适配器(对象适配器)
          • 9.5 特定适配器(类适配器)
          • 9.6 化解难以调和的矛盾

            9、适配器模式

            9.1 适配器模式
            • 适配器模式(Adapter)通常也被称为转换器(适应与匹配)
            • 当一个对象或类的接口不能匹配用户所期待的接口时,适配器就充当中间转换的角色,达到兼容用户接口的目的
            • 适配器也实现了客户端与接口的解耦,提高了组件的可复用性
            • 测试类结构

              秒懂设计模式--学习笔记(10)【结构型-适配器模式】

              9.2 翻译(举例)
              • 不懂英文的人与不懂中文的人交流,双方都听不懂对方说什么
              • 找个会两种语言的翻译官
              • 双方通过翻译官进行交流
              • 这个翻译官就相当于适配两个不兼容接口的适配器
                9.3 插头与插座(举例)
                • 两脚插头与三孔插座
                • 定义通电标准接口:DualPin(两插)、TriplePin(三相)
                  package adapter;
                  /**
                   * @Description 两插
                   */
                  public interface DualPin {
                      /**
                       * 两脚插头: 通电标准
                       * @param l 火线(live)
                       * @param n 零线(null)
                       */
                      public void electrify(int l, int n);
                  }
                  
                  package adapter;
                  /**
                   * @Description 三相
                   */
                  public interface TriplePin {
                      /**
                       * 三孔插座: 通电标准
                       * @param l 火线(live)
                       * @param n 零线(null)
                       * @param e 地线(earth)
                       */
                      public void electrify(int l,int n, int e);
                  }
                  
                  • 定义两插的电视机类TVDualPinImpl
                    package adapter.impl;
                    import adapter.DualPin;
                    /**
                     * @Description 两脚插头的电视机类
                     */
                    public class TVDualPinImpl implements DualPin {
                        @Override
                        public void electrify(int l, int n) {
                            System.out.println("火线通电:" + l + ",零线通电:" + n);
                            System.out.println("电视开机");
                        }
                    }
                    
                    • 但是到这里,可以看到两插和三相的通电便准并不一致,这个两插电视机并不能使用三孔插座进行开机,接口不兼容会提示类型不匹配,如测试类Client.test1()
                      package adapter;
                      import adapter.impl.TVDualPinImpl;
                      /**
                       * @Description 测试类
                       */
                      public class Client {
                          /**
                           * 这个两脚电视机并不能使用三孔插座进行开机
                           * 接口不兼容会提示类型不匹配
                           */
                          private static void test1() {
                          	// 这一行会提示错误
                              TriplePin triplePinDevice = new TVDualPinImpl();
                          }
                      }
                      
                      9.4 通用适配器(对象适配器)
                      • 极端解决方案: 将三孔插座改成两孔插座,三相变两相。这样的话就不能再使用三相了
                      • 如果通过一个中间件来进行兼容适配的话,可以不改变插座原来的功能,而又兼容了两脚插座的使用
                      • 制作一个电源转换器AdapterTriplePinImpl来适配,承上启下,解决接口冲突问题
                        • 适配器实现三相接口
                        • 然后在构造时传入需要被适配的两插接口(表示将两脚接口适配到三孔插座)
                        • 在实现通电方法时,适配器转换两插,达到适配效果
                        • 至此,该适配器就可以将任意两脚插头,匹配到三孔插座了
                          package adapter.impl;
                          import adapter.DualPin;
                          import adapter.TriplePin;
                          /**
                           * @Description 三相适配器(实现三相接口):在三孔插座与两脚插头之间做适配
                           */
                          public class AdapterTriplePinImpl implements TriplePin {
                              /**
                               * 适配:两插(任何此规格的设备都是可以接入进来的)
                               */
                              private DualPin dualPin;
                              /**
                               * 创建适配器:传入需要与三孔插座适配的两脚插头
                               * @param dualPin
                               */
                              public AdapterTriplePinImpl(DualPin dualPin) {
                                  this.dualPin = dualPin;
                              }
                              /**
                               * 适配器实现
                               * @param l 火线(live)
                               * @param n 零线(null)
                               * @param e 地线(earth)
                               */
                              @Override
                              public void electrify(int l, int n, int e) {
                                  // 被适配的方法,忽略地线e
                                  dualPin.electrify(l, n);
                              }
                          }
                          
                          • 使用适配器进行接入,Client.test2()
                                /**
                                 * 对象适配器兼容两插和三孔设备
                                 *      输出结果:
                                 *          火线通电:1,零线通电:0
                                 *          电视开机
                                 */
                                private static void test2() {
                                    // 两插电视机(需要进行适配的)
                                    DualPin tvDualPin = new TVDualPinImpl();
                                    // 适配器,串联两插和三孔:将电视机两相插头插入适配器,并将匹配好的适配器插入墙上的三相插孔
                                    TriplePin triplePin = new AdapterTriplePinImpl(tvDualPin);
                                    // 底层使用三孔(适配)的通电标准:直接调用三插通电方法给电视机供电
                                    triplePin.electrify(1, 0, -1);
                                }
                            
                            • 适配器并不关心接入的设备是电视机还是电冰箱,只要是两相插头的设备均可以进行适配,所以说它是一种通用的适配器
                              9.5 特定适配器(类适配器)
                              • 属于某个类的“专属适配器”,也就是在编码阶段已经将被匹配的设备与目标接口进行对接了
                              • 电视机专属适配器类TVAdapter,继承两插电视机类,实现三相接口类:
                                • 类适配器模式实现起来更简单
                                • 继承两插电视,表明该适配器兼容两插
                                • 实现三项接口,表明该适配器适配三相
                                • 重写三相通电方法
                                • 在通电方法中,使用“super”关键字调用父类(电视机类TV)定义的两插通电方法,以实现适配
                                  package adapter.impl;
                                  import adapter.TriplePin;
                                  /**
                                   * @Description 电视机专属适配器类:
                                   *                  类适配器模式实现起来更简单
                                   *                  继承两插电视,表明该适配器兼容两插
                                   *                  实现三项接口,表明该适配器适配三相
                                   */
                                  public class TVAdapter extends TVDualPinImpl implements TriplePin {
                                      /**
                                       * 重写三相通电方法
                                       * @param l 火线(live)
                                       * @param n 零线(null)
                                       * @param e 地线(earth)
                                       */
                                      @Override
                                      public void electrify(int l, int n, int e) {
                                          // “super”关键字调用父类(电视机类TV)定义的两插通电方法,以实现适配
                                          super.electrify(l, n);
                                      }
                                  }
                                  
                                  • 测试Client.test3()
                                        /**
                                         * 类适配器,类适配器模式不但使用起来更加简单,其效果与对象适配器模式毫无二致
                                         *      输出结果:
                                         *          火线通电:1,零线通电:0
                                         *          电视开机
                                         */
                                        private static void test3() {
                                            // 电视机专属三插适配器插入三相插孔
                                            TriplePin tvAdapter = new TVAdapter();
                                            // //此处调用的是三插通电标准
                                            tvAdapter.electrify(1, 0, -1);
                                        }
                                    
                                    • 类适配器模式不但使用起来更加简单,而且其效果与对象适配器模式毫无二致。
                                    • 这个类适配器是继承自电视机的子类,在类定义的时候就已经与电视机完成了接驳
                                    • 也就是说,类适配器与电视机的继承关系让它固化为一种专属适配器,这就造成了继承耦合
                                    • 倘若我们需要适配其他两插设备,就不得不再写一个“洗衣机专属适配器”
                                    • 适配器兼容性较差
                                      9.6 化解难以调和的矛盾
                                      • 适配器模式让兼容性问题在不必修改任何代码的情况下得以解决,其中适配器类是核心
                                      • 对象适配器模式的各角色定义如下
                                        • Target(目标接口):客户端要使用的目标接口标准,TriplePin。
                                        • Adapter(适配器):实现了目标接口,负责适配(转换)被适配者的接口为目标接口,AdapterTriplePinImpl。
                                        • Adaptee(被适配者):被适配者的接口标准,目前不能兼容目标接口的问题接口,可以有多种实现类,DualPin。
                                        • Client(客户端):目标接口的使用者
                                        • 类适配器模式的各角色定义如下
                                          • Target(目标接口):客户端要使用的目标接口标准,TriplePin。
                                          • Adapter(适配器):继承自被适配者类且实现了目标接口,负责适配(转换)被适配者的接口为目标接口,TVAdapter
                                          • Adaptee(被适配者):被适配者的类实现,目前不能兼容目标接口的问题类,TVDualPinImpl
                                          • Client(客户端):目标接口的使用者
                                          • 对象适配器模式与类适配器模式基本相同,二者的区别在于
                                            • 对象适配器的Adaptee(被适配者)以接口形式出现并被Adapter(适配器)引用(更灵活)
                                            • 类适配器以父类的角色出现并被Adapter(适配器)继承(更简单)、
                                            • 适配器至少都应该具备模块两侧的接口特性
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]