• 设计模式:适配器模式


    适配器模式(Adapter Pattern),别名Wrapper。

    适配器模式分为两种:对象适配器模式;类适配器模式。

    理解类图需要知道的一些基本名词和符号:UML类图的几个名词及对应符号

    对象适配器模式

    Client想要调用某个具体Adaptee的方法,来实现某个功能A。最直接的做法是将Adaptee作为参数传入,然后让Client创建一个方法去调用。
    如果Client也想调用另一个具体Adaptee的方法,也实现某个功能A。此时再将Adaptee作为参数传入,然后让Client创建一个方法去调用。
    ……
    当Client想调用一百个类(甚至不止这些)的方法,来实现同一个功能A,那不就得添加一百个方法?真这么做,这个类就太臃肿了。并且,在某个具体的系统,极大部分的方法都不会被用到。

    那么,提取出一个接口(Target),并让Client调用这个接口的方法不就行了吗?这样Client就不需要为某个具体的类添加方法。 问题就这样解决了,但还没结束。

    既然有一个接口,那么不就意味着每个具体Adaptee都要实现这个接口了么?最理想的情况是,这些类刚好那个被调用的方法的方法名是相同的,直接加个implements xxx就行了(前提是你被允许修改这些类的代码)。

    当然,现实并不是这么理想。它们的方法名往往不同,而你也不被允许修改它们的代码,更不用说去这些类里面去实现这些方法。

    那TM怎么办?

    先把已知条件整理出来:已知Client会调用Target接口的某个方法,但是具体类的方法名与接口的方法名不匹配,不能让具体类实现Target接口并传入Client。
    问:如何让Client只调用Target接口的方法而间接地调用到具体类的方法?

    答:创建一个类(MyAdapter),这个类里有一个方法,其方法名与Target定义的方法名完全一致(假设为sayHello())。接着将具体的类(假设为 RudeMan)传入这个新建的类,在 sayHello() 里面调用具体类的方法(假设为 sayFuck())。这就相当于给RudeMan的sayFuck()方法包装了另一个名字。
    既然MyAdapter的方法名与Target定义的一致,那么就可以加上implements xxx了。

    public class MyAdapter implements Target {
        private RudeMan rudeMan = null;
        
        public MyAdapter(RudeMan man) {
            rudeMan = man;
        }
        
        public void sayHello() {
            rudeMan.sayFuck();
        }
    }
    

    这时,MyAdapter类相当于是一个转接口,将具体类RudeMan的具体方法包装成另一个名字。并且MyAdapter实现了Target接口,可以传入Client供其调用。

    类适配器模式

    由于类适配器模式有时需要多重继承,而JAVA不支持,所以通常不使用类适配器模式。

    对于类适配器模式的方式,你会看到这样的形式:

    public class Adapter extends Adaptee implements Target {
    ……
    }
    

    这里extends是为了调用具体类Adaptee的方法,而implements是为了让Client调用已被Target定义好的方法。

    从UML类图角度来对比两者

    对象适配器模式:基本聚合
    类适配器模式:泛化

  • 相关阅读:
    linux 内核升级
    maven 热部署至tomcat
    Executor多线程框架使用
    数据库中的一些连接
    Ajax传统操作
    第三篇、简单的图片下载器
    第二篇、通过蓝牙连接外设
    第一篇、实现上拉和下拉刷新
    解决Git报错:The current branch is not configured for pull No value for key branch.master.merge found in configuration
    Spark核心概念
  • 原文地址:https://www.cnblogs.com/schaepher/p/6278538.html
Copyright © 2020-2023  润新知