zoukankan      html  css  js  c++  java
  • 适配器模式--Adapter Pattern

      模拟场景:很多人都喜欢看NBA吧,姚明进驻NBA,打开了中国的市场。虽然后面姚明在NBA打得还不错,但是在刚进入NBA篮坛的时候,并不是那么顺利的。语言交流就是一个最大的问题。刚开始打球期间,教练及队员的战术部署姚明都无法理解,所以他需要这么一个翻译者,将教练及队员的意思转达给姚明,这样才可以进行合作。

      现在进行场景的模拟,先不考虑那么多。假如姚明一开始进入NBA的时候就已经会英语,可以进行交流了。那么这个时候教练就可以进行战术的部署了。

      转换成类,所有的队员都要服从教练的战术要求,假设现在教练都要给队员部署进攻和防守的指令。所有大家接收的动作是一致的,只是实现不一样而已。所有这里需要先定义出一个接口或者抽象类。

    IPlayer 

     1 package com.zqz.dp.adapter;
     2 /**
     3  * @author Qin 所有运动员的父接口,完成同样的动作
     4  */
     5 public interface IPlayer {
     6     /**
     7      * 运动员进攻
     8      */
     9     void attack();
    10     /**
    11      * 运动员防守
    12      */
    13     void defense();
    14 }

      构建完接口之后,就是对接口进行实现了。假设现在有前锋forwards、中锋center、后卫guards三种运动员,来根据教练的指令完成不同的动作。

    Forwards

     1 package com.zqz.dp.adapter;
     2 /**
     3  * @author Qin
     4  * 前锋类,实现运动员接口,实现自己的动作
     5  */
     6 public class Forwards implements IPlayer {
     7     private String name;    //定义运动员的名字
     8     public Forwards(String name) {        //构造方法赋值
     9         this.name = name;
    10     }
    11     @Override
    12     public void attack() {
    13         System.out.println("前锋〖"+this.name+"〗攻击。。。");
    14     }
    15     @Override
    16     public void defense() {
    17         System.out.println("前锋〖"+this.name+"〗防守。。。");
    18     }
    19 }

    Center

     1 package com.zqz.dp.adapter;
     2 /**
     3  * @author Qin
     4  * 中锋类,实现运动员接口,实现自己的动作
     5  */
     6 public class Center implements IPlayer {
     7     private String name;    //定义运动员的名字
     8     public Center(String name) {        //构造方法赋值
     9         this.name = name;
    10     }
    11     @Override
    12     public void attack() {
    13         System.out.println("中锋〖"+this.name+"〗攻击。。。");
    14     }
    15     @Override
    16     public void defense() {
    17         System.out.println("中锋〖"+this.name+"〗防守。。。");
    18     }
    19 }

    Guards

     1 package com.zqz.dp.adapter;
     2 /**
     3  * @author Qin
     4  * 后卫类,实现运动员接口,实现自己的动作
     5  */
     6 public class Guards implements IPlayer {
     7     private String name;    //定义运动员的名字
     8     public Guards(String name) {        //构造方法赋值
     9         this.name = name;
    10     }
    11     @Override
    12     public void attack() {
    13         System.out.println("后卫〖"+this.name+"〗攻击。。。");
    14     }
    15     @Override
    16     public void defense() {
    17         System.out.println("后卫〖"+this.name+"〗防守。。。");
    18     }
    19 }

    Client

     1 package com.zqz.dp.adapter;
     2 /**
     3  * @author 
     4  * Qin 场景类,模拟NBA比赛
     5  */
     6 public class Client {
     7     public static void main(String[] args) {
     8         IPlayer ba=new Forwards("巴蒂尔");
     9         ba.attack();
    10         IPlayer yao=new Center("姚明");
    11         yao.attack();
    12         yao.defense();
    13         IPlayer mai=new Guards("麦迪");
    14         mai.defense();
    15     }
    16 }

      以上的操作很简单,说白了就是父类引用指向子类实例,但是现在姚明是直接可以听懂了教练的战术安排了,这个已经是后面发展得很好的姚明了。并不是一开始不能进行交流的那个大姚了。

      要模拟刚入NBA的大姚,那么说明需要创建一个新的类来表示大姚这个对象。在这里我们把Center改成foreignCenter,表示外籍中锋。而很明显这个时候大姚根本无法听懂教练的意思,所以需要一个翻译者translator,翻译者是可以听懂教练的意思的,但是听懂了总不能自己上场比赛吧,所以要把教练的意思传递给大姚,交给大姚去执行。

      转化为类之间的关系也就是translator类要实现IPlayer接口,并且要有一个fireignCenter的引用,具体的实现交给引用去调用自己的方法。

    ForeignCenter

     1 package com.zqz.dp.adapter;
     2 /**
     3  * @author Qin 
     4  * 外籍中锋类,外籍中锋是新引进的类,并不能听懂教练的意思,所以只能执行自己的功能
     5  */
     6 public class ForeignCenter {
     7     private String name; // 定义运动员的名字
     8     public ForeignCenter(String name) { // 构造方法赋值
     9         this.name = name;
    10     }
    11     public void attack() {
    12         System.out.println("外籍中锋〖" + this.name + "〗攻击。。。");
    13     }
    14     public void defense() {
    15         System.out.println("外籍中锋〖" + this.name + "〗防守。。。");
    16     }
    17 }

    Translator

     1 package com.zqz.dp.adapter;
     2 /**
     3  * @author Qin
     4  * 翻译者类,适配器对象。传递教练的意思给外籍中锋
     5  */
     6 public class Translator implements IPlayer {
     7     private ForeignCenter fc;
     8     public Translator() {    //翻译者类知道要把消息传递给谁,所以立即生成外籍中锋实例
     9         fc=new ForeignCenter("大姚");
    10     }
    11     @Override
    12     public void attack() {
    13         this.fc.attack();    //告诉大姚要进行攻击
    14     }
    15     @Override
    16     public void defense() {
    17         this.fc.defense();    //告诉大姚进行防守
    18     }
    19 }

      其他类不变。这样就完成了功能,由翻译者转达大姚进行战术的安排。

      上面的操作其实很简单,只是在执行的时候调用的是具体真实类的操作而已。是否会觉得有点跟代理类似,其实会这样觉得是因为我把ForeignCenter中的方法定义成和IPlayer的方法一致。也就是说虽然教练给大姚下达了战术的安排,但是大姚可以执意按自己的想法进行安排。所以这也是和代理不同的地方。

      以上的操作就是适配器模式,准确来说是对象适配器,因为在类中传递了另一个类的引用。还有另一种叫做类适配器。要实现类适配器就方便多了,只要让Translator继承ForeignCenter即可,再调用父类的方法。很明显在这里是不合适的,因为两者不存在is-a的关系,所以在真正开发中,对象适配器用的必类适配器多。

      听名字大家就应该能明白意思了,何为适配器?就是把两个不合适的对象通过一个中间对象连接起来。像我们平常的电池充电不也需要一个电源适配器吗?就是一样的道理。

      适配器模式是一个补救的模式,也就是说一般在开发前期不会考虑该模式,而是在后期扩展中才会考虑到。还是以上面的例子为例,NBA事先根本就不能料想到是否会有中国球员参加比赛,所以才会有翻译者的存在,翻译者就是一个适配器。

    适配模式的优点:

      1、  适配器可以将两个毫无关联的对象连接起来。

      2、  增加了类的透明度:也就是说教练根本不用管大姚,直接告诉翻译者如何做就行了。

      3、  提高了类的复用性,易扩展,灵活性好。

    适配器的使用场景:

      你有动机去修改一个已经投入生产的接口时,就可以使用适配器进行扩展。

    适配器的拓展:

      除了类适配器和对象适配器外,还有一种缺省适配器,所谓的缺省适配器就是说在一个接口中存在了一大堆的方法,但是我们在具体的实现中根本就不需要这么多方法,那么我们就可以创建一个中间类,把这些方法全部空实现,然后具体的类再继承该空实现的类,完成自己所需要的功能。

  • 相关阅读:
    过河问题 (Standard IO)
    单词分类 (Standard IO)
    C#综合揭秘——细说多线程(上)
    使用NPOI导入导出标准Excel
    C# 转义字符 ''反斜杠
    ref和out的区别
    抽象类接口的区别
    方法签名
    SQL Server的通用分页存储过程 未使用游标,速度更快!
    SQL Server存储过程Return、output参数及使用技巧
  • 原文地址:https://www.cnblogs.com/littleQin/p/3695482.html
Copyright © 2011-2022 走看看