聊聊Swift中的设计模式---结构型(适配器模式)

368 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情


前言

在面向对象的开发过程中,其实咱们或多或少的都接触过一些设计模式,可能知道或不知道其对应的名称,也不知道其具体使用场景,今天咱们就来说说几种常见的设计模式,帮助你们在开发过程中,更加得心应手。

下面还有其他模式

创建型-工厂模式

创建型-建造者模式

正文

什么是适配器模式呢?

举个栗子:

假如我的手机充电口是 type-c 类型的,但我只有一根传统的 USB 接口的数据线,怎么办?

type-c 类型的接口就是需求接口。

USB 类型的接口是供应接口。

想让需求匹配供应,就需要有一个适配器。

适配器模式就是将两个本不可以兼容的东西进行兼容或者链接起来。就像把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。

类适配器

当需要把一个已经实现了接口a的类A,转换成能实现接口b的类时,可使用类适配器模式。

注意:类A是已经设计好的,不能改变。

创建一个新类,实现接口,继承原有的类即可。

/// 供应接口
protocol MicroUSB {
    func microUSB()
}

/// 需求接口
protocol TypeC {
    func typeC()
}

class Phone : TypeC {
    func typeC() {
        print("Type-C 接口")
    }
}

/// 适配器
class Adapter : Phone, MicroUSB {
    func microUSB() {
        typeC()
    }
}

let microUSB = Adapter()
microUSB.microUSB() // Type-C 接口

在这个例子中,由于某种原因class Phone: TypeC 这个继承自TypeCphone不能动,想要使用protocol MicroUSBmicroUSB()的方法去输出--『Type-C 接口』就只能新增一个类Adapter

Adapter 继承自Phone,同时也遵守MicroUSB的协议。在其内部实现了一个microUSB的函数,用来调用Phone中的typeC()方法。

这样就完成了在不改变原有class Phone: TypeC里面方法的同时,输出原有的内容。


对象适配器

当希望将接口A的实现类A的对象转换成满足接口B的对象时,可使用对象适配器的方式。

/// 供应接口
protocol MicroUSB {
    func microUSB()
}

/// 需求接口
protocol TypeC {
    func typeC()
}

class Phone : TypeC {
    func typeC() {
        print("Type-C 接口")
    }
}

/// 适配器
class Adapter: MicroUSB {
    
    private var typeC: TypeC
    
    init(typeC: TypeC) {
        self.typeC = typeC
    }
    
    func microUSB() {
        self.typeC.typeC()
    }
}

let typeC: TypeC = Phone()
let microUSB = Adapter(typeC: typeC)
microUSB.microUSB() // Type-C 接口

在这个例子中,咱们是通过在Adapter(适配器)中创建一个TypeC类型的变量,从而能使用typeC()这个方法的,Adapter初始化时就传入对应的typeC实例。


接口适配器

有一个很大的接口,包含很多方法,当不希望实现接口中的所有方法时,可创建一个抽象类继承接口,但方法实现都是空的,实现类可继承这个抽象类实现了适配器的功能。

看看下面这个例子:

日常用的转换器有很多种类型的接口,比如 type-C,VGA,Hdmi,可以把这些类型都放在一个大的接口中,当我只需type-C 和 VGA 类型的转换器时,继承相关的类即可。

/// 接口类
protocol AllPorts {
    func typeC()
    func vga()
    func hdmi()
}

/// 适配器
class Adapter : AllPorts {
    func typeC() { }
    func vga() { }
    func hdmi() { }
}

/// 适配器类
class TypeCToVGA : Adapter {
    override func typeC() {
        print("信号从TypeC接口进入")
    }
    override func vga() {
        print("信号从VGA接口出来")
    }
}

let typecToVGA: TypeCToVGA = TypeCToVGA()
typecToVGA.typeC()
typecToVGA.vga()

接口适配器其实比较好理解,就是我要什么东西,就定义一个类,继承自这个适配器,然后重写里面的放方法。

这样在外部调用的时候,就可以直接使用了。

为什么不直接使用适配器去初始化一个实例呢?

因为,适配器里定义的函数都没写实现方法,你只用继承适配器后,自己去实现方法就行,将耦合度降低。

结语

类适配器、接口适配器、对象适配器,这3种适配器其实在咱们开发过程中还比较常见,只是不知道叫什么,我想通过这篇文章,应该可以带大家清楚的了解适配器的作用。