设计模式3.1&3.2 适配器模式与缺省适配模式

字节跳动飞书内推!
北京、杭州、武汉、广州、深圳、上海,六大城市等你来投。
感兴趣的朋友可以私我咨询&内推,也可以通过链接直接投递
海量HC,极速响应,快来和我成为同事吧。
今日头条、抖音、Tik Tok也可以内推~

点击进入我的博客

3.1 适配器模式

适配器模式把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

3.1.1 类的适配器结构

类的适配器
  • 目标(Target)角色:这就是所期待得到的接口,由于是类适配器模式,因此目标不可以是类。
  • 源(Adaptee)角色:现有需要适配的接口。
  • 适配器(Adapter)角色:适配器类是本模式的核心,必须是具体类。
interface Target {
    void operation1();
    void operation2();
}

class Adaptee {
    public void operation1() {}
}

class Adapter extends Adaptee implements Target {
    @Override
    public void operation2() {}
}
类的适配器
  • 类的适配器模式把被的类的API转换成目标类的API。
  • 是通过继承实现的。
类的适配器效果
  • 使用一个具体类把源适配到目标中。这样如果源以及源的子类都使用此类适配,就行不通了。
  • 由于适配器是源的子类,因此可以在适配器中重写源的一些方法。
  • 由于引进了一个适配器类,因此只有一个线路到达目标类,是问题得到简化。

3.1.2 对象的适配器结构

对象适配器
  • 目标(Target)角色:这就是所期待得到的接口,因此目标可以是具体或抽象的类
  • 源(Adaptee)角色:现有需要适配的接口。
  • 适配器(Adapter)角色:适配器类是本模式的核心,必须是具体类。
interface Target {
    void operation1();
    void operation2();
}

class Adaptee {
    public void operation1() {}
}

class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void operation1() {
        adaptee.operation1();
    }

    @Override
    public void operation2() {
        // do something
    }
}
对象的适配器
  • 对象的适配器是通过依赖实现的
  • 推荐使用该方法
对象的适配器效果
  • 一个适配器可以把多种不同的源适配到同一个目标,即同一个适配器可以把源类和它的子类都适配到目标接口
  • 与类的适配器模式相比,要想置换源类的方法就不容易。
  • 增加新的方法方便的多

3.1.3 细节

使用场景
  1. 系统需要使用现有的类,而此类的接口不符合系统的需要
  2. 想要建立一个可以重复使用的类,用于与一些彼此间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
  3. 对对象的适配器儿模式而言,在设计里,需要改变多个已有的子类的接口,如果使用类的适配器模式,就需要针对每个子类做一个适配器类,这不太实际。
优点
  1. 可以让任何两个没有关联的类一起运行。
  2. 提高了类的复用。
  3. 增加了类的透明度。
  4. 灵活性好。
缺点
  1. 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
  2. 由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。
注意点
  1. 目标接口可以忽略,此时目标接口和源接口实际上是相同的
  2. 适配器类可以是抽象类
  3. 可以有带参数的适配器模式

3.1.4 一个充电器案例

// 充电器只能接受USB接口
public class Charger {
    public static void main(String[] args) throws Exception{
        USB usb = new SuperAdapter(new TypeC());
        connect(usb);
        usb = new SuperAdapter(new Lightning());
        connect(usb);
    }

    public static void connect(USB usb) {
        usb.power();
        usb.data();
    }
}

// 充电器的接口都是USB的,假设有两个方法分别是电源和数据
interface USB {
    void power();
    void data();
}

// IOS的Lightning接口
class Lightning {
    void iosPower() {
        System.out.println("IOS Power");
    }
    void iosData() {
        System.out.println("IOS Data");
    }
}

// TYPE-C接口
class TypeC {
    void typeCPower() {
        System.out.println("TypeC Power");
    }
    void typeCData() {
        System.out.println("TypeC Data");
    }
}

// 超级适配器,可以适配多种手机机型
class SuperAdapter implements USB {
    private Object obj;

    public SuperAdapter(Object obj) {
        this.obj = obj;
    }

    @Override
    public void power() {
        if(obj.getClass() == Lightning.class) {
            ((Lightning)obj).iosPower();
        } else if(obj.getClass() == TypeC.class) {
            ((TypeC)obj).typeCPower();
        }
    }

    @Override
    public void data() {
        if(obj.getClass() == Lightning.class) {
            ((Lightning)obj).iosData();
        } else if(obj.getClass() == TypeC.class) {
            ((TypeC)obj).typeCData();
        }
    }
}

3.2 缺省适配模式

缺省适配模式为一个接口提供缺省实现,这样子类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。

3.2.1 缺省适配模式结构

缺省适配模式
简单的例子
  • 下面程序中,Monk接口定义了两个方法,于是它的子类必须实现这两个方法。
  • 但出现了一个LuZhiShen,他只能实现一部分方法,另一部分方法无法实现
  • 所以需要一个抽象的适配类MonkAdapter实现此Monk接口,此抽象类给接口所有方法都提供一个空的方法,LuZhiShen只需要继承该适配类即可。
// 和尚
interface Monk {
    void practiceKungfu();
    void chantPrayer();
}

abstract class MonkAdapter implements Monk {
    @Override
    public void practiceKungfu() {}

    @Override
    public void chantPrayer() {}
}

class LuZhiShen extends MonkAdapter {
    @Override
    public void practiceKungfu() {
        System.out.println("拳打镇关西");
    }
}

3.2.2 细节

使用场景
  • 任何时候不准备实现一个接口中所有方法的时候
作用

缺省适配器模式可以使所需要的类不必实现不需要的接口。

核心点
  • 缺省适配的类必须是抽象类,因为这个类不应当被实例化
  • 缺省适配的类提供的方法必须是具体的方法,而不是抽象的方法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容