用来解决接口适配问题的三种模式:适配器模式,桥接模式,外观模式。

一,概念

  适配器模式,将一个类的结构转换成用户希望的另一个接口,使得原本接口不兼容的类能在一起工作。换句话说,适配器模式就是链接两种不同种类的对象,使其很好的协同工作。(说的很美吧,我抄的,百度里每个帖子都会这样说。简单说就是你笔记本是19v供电,但是家里面电压是220v,这时候想要充电,就需要一个笔记本的220v转19v电源适配器)。

  有两种实现结构(类的适配器,对象的适配器),还有说三种(接口的适配器方式),额。

二,模式结构图

  了解三个角色,结合结构图理解:

    Target:目标角色定义客户端具体使用的接口,也就是我们的期望接口,简单一点就是协议,协议定义我们需要的接口

    Adaptee:源角色,你想把“谁”转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象。

    Adapter:适配器角色,适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,他的职责非常简单:把源角色转换为目标角色。

  类的适配器模式:

  

  Adapter是一个Target(目标接口)类型,同时也是一个Adaptee(被适配的类)类型。Adapter重载Target的request方法,但没有重载Adaptee的specificRequest方法,而是在其request方法中调用父类的specificRequest方法(即:[super specificRequest])。当request方法在运行时,向Adaptee发送super消息时,Adaptee按自己的方式执行specificRequest方法。注意:只有当Target是协议而不是类时,类适配器才能用Objective-C实现。

  对象的适配器模式:

  

  Target和Adapter之间的关系与类适配器相同,而Adapter和Adaptee之间的关系从“属于(继承)”变成了“包含(组合引用)”。这种情况下Adapter持有一个对Adaptee的引用,在request方法中,Adapter发送[adaptee specificRequest]消息,以间接方法Adaptee的specificRequest方法,然后实现客户端请求的其他部分。

三,使用场景:(也是copy的,多读读回忆下项目代码就能理解了)

  1:你想使用一个已经存在的类,而它的接口不符合你的需求,即已有类的接口与需求不匹配
  2:你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作
  3:(仅适用于对象Adapter)你想使用一些已存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口,对象适配器可以适配它的父类接口

四,Demo演示:
  下面有个场景,已经存在一个UniversulAudioPlayer类,可以进行音频的播放。但是ViewController端需要的是一个遵守了AudioPlayerProtocol协议接口的类对象 AudioPlayerProtocol协议规范了ViewController调用接口,她和UniversulAudioPlayer已经实现的接口并不匹配。代码如下:

Target

protocol AudioPlayerProtocol {

    /// setting media source
///
/// - Parameter url: source url
/// - Returns: whether success
func prepareWithUrl(url: URL) -> Bool /// jump to playing time point
///
/// - Parameter time: the time point 0 - media.duration
/// - Returns: whether success
func jumpTo(time: TimeInterval) -> Bool /// increase valume,add 0.1 once, value0 - 1
///
/// - Returns: Voide
func increaseVolume() -> Void /// reduce Volume
///
/// - Returns: Void
func reduceVolume() -> Void /// start to play the audio
///
/// - Returns:
func play() -> Void /// pause the audio
///
/// - Returns:
func pause() -> Void /// resume to play
///
/// - Returns:
func resume() -> Void
}

Adapee

class UniversulAudioPlayer: NSObject {

    private var url: URL?
private var duration: TimeInterval = 0
private var volumeValue: Float = 0
private var timeValue: TimeInterval = 0 var volume: Float{
set{
if newValue <= 0 {
self.volumeValue = 0
}else if newValue >= 1{
self.volumeValue = 1.0
}else{
self.volumeValue = newValue
}
print("new volume: \(self.volumeValue)")
}
get{
return self.volumeValue
}
} var time: TimeInterval{
set{
if newValue >= 0.0 && newValue <= duration {
self.timeValue = newValue
print("new time: \(newValue)")
}
}
get{
return self.timeValue
}
} func audioWithUrl(url: URL) -> Bool {
print("setting url: \(url)")
self.duration = 300;
self.url = url;
return true
} func playAudio() {
if url != nil {
print("start\resume to play audio \(url!)")
}else{
print("play fail")
}
} func pauseAudio() {
if url != nil {
print("pause audio \(url!)")
}else{
print("play fail")
}
}
}

Client

class ViewController: UIViewController {

    var player: AudioPlayerProtocol!

    override func viewDidLoad() {
super.viewDidLoad()
// player = MyUniversulAudioPlayer()
player = TheUniversulAudioPlayer()
player.prepareWithUrl(url: URL(string: "http://www.y.com/music/a.mp3")!)
} //按钮事件 @IBAction func playBtnClicked(_ sender: Any) {
player.play()
} @IBAction func pauseBtnClicked(_ sender: Any) {
player.pause()
} @IBAction func resumeBtnClicked(_ sender: Any) {
player.resume()
} @IBAction func increaseVolumeBtnClicked(_ sender: Any) {
player.increaseVolume()
} @IBAction func reduceVolumeBtnClicked(_ sender: Any) {
player.reduceVolume()
} }

所以,就需要我们做一个适配器
1,类的适配器模式:

class MyUniversulAudioPlayer: UniversulAudioPlayer, AudioPlayerProtocol {
func prepareWithUrl(url: URL) -> Bool {
return super.audioWithUrl(url: url)
} func jumpTo(time: TimeInterval) -> Bool {
super.time = time
return true
} func increaseVolume() {
self.volume += 0.1
} func reduceVolume() {
self.volume -= 0.1
} func play() {
self.playAudio()
} func pause() {
self.pauseAudio()
} func resume() {
self.playAudio()
} }

2,对象的适配器模式

class TheUniversulAudioPlayer: AudioPlayerProtocol {

    private var universulPlayer = UniversulAudioPlayer()

    func prepareWithUrl(url: URL) -> Bool {
return universulPlayer.audioWithUrl(url: url)
} func jumpTo(time: TimeInterval) -> Bool {
universulPlayer.time = time
return true
} func increaseVolume() {
universulPlayer.volume += 0.1
} func reduceVolume() {
universulPlayer.volume -= 0.1
} func play() {
universulPlayer.playAudio()
} func pause() {
universulPlayer.pauseAudio()
} func resume() {
universulPlayer.playAudio()
} }

  

设计模式-(6)适配器 (swift版)的更多相关文章

  1. iOS可视化动态绘制八种排序过程(Swift版)

    前面几篇博客都是关于排序的,在之前陆陆续续发布的博客中,我们先后介绍了冒泡排序.选择排序.插入排序.希尔排序.堆排序.归并排序以及快速排序.俗话说的好,做事儿要善始善终,本篇博客就算是对之前那几篇博客 ...

  2. Swift版iOS游戏框架Sprite Kit基础教程下册

    Swift版iOS游戏框架Sprite Kit基础教程下册 试读下载地址:http://pan.baidu.com/s/1qWBdV0C 介绍:本教程是国内唯一的Swift版的Spritekit教程. ...

  3. Swift版音乐播放器(简化版),swift音乐播放器

    这几天闲着也是闲着,学习一下Swift的,于是到开源社区Download了个OC版的音乐播放器,练练手,在这里发扬开源精神, 希望对大家有帮助! 这个DEMO里,使用到了 AudioPlayer(对音 ...

  4. 快速排序OC、Swift版源码

    前言: 你要问我学学算法在工作当中有什么用,说实话,当达不到那个地步的时候,可能我们不能直接的感觉到它的用处!你就抱着这样一个心态,当一些APP中涉及到算法的时候我不想给其他人画界面!公司的项目也是暂 ...

  5. swift版的CircleView

    swift版的CircleView 效果图 源码 // // CircleView.swift // CircleView // // Created by YouXianMing on 15/10/ ...

  6. swift版的GCD封装

    swift版的GCD封装 说明 本人针对swift封装了GCD,包括GCDQueue,GCDGroup,GCDTimer以及GCDSemaphore,使用较为便利. 源码 https://github ...

  7. swift版的StringAttribute

    swift版的StringAttribute 效果 源码 https://github.com/YouXianMing/Swift-StringAttribute // // StringAttrib ...

  8. swift版的元组

    swift版的元组 说明 元组的内容并不多,使用的话跟普通变量类似,以下是测试源码: // // ViewController.swift // Tuples // // Created by You ...

  9. swift版的枚举变量

    swift版的枚举变量 swift的枚举类型跟普通的类是极为类似的,使用的时候,请不要以为他是一个常量,以下是测试用源码 // // ViewController.swift // SwiftEnum ...

  10. 关东升的iOS实战系列图书 《iOS实战:入门与提高卷(Swift版)》已经上市

             承蒙广大读者的厚爱我的 <iOS实战:入门与提高卷(Swift版)>京东上市了,欢迎广大读者提出宝贵意见.http://item.jd.com/11766718.html ...

随机推荐

  1. POJ 4118 开餐馆

    Description 北大信息学院的同学小明毕业之后打算创业开餐馆.现在共有n 个地点可供选择.小明打算从中选择合适的位置开设一些餐馆.这 n 个地点排列在同一条直线上.我们用一个整数序列m1, m ...

  2. HR面试你需要注意什么?

    公司的面试流程一般是笔试—>技术面试—>hr面试,在大部分应聘测试工程师这种技术岗的应聘者理解中,通常认为通过技术面试了,后面的hr面试基本就是走流程过形式.也正因如此,我们习惯性地把精力 ...

  3. zoj 1240

    IBM Minus One Time Limit: 2 Seconds      Memory Limit: 65536 KB You may have heard of the book '2001 ...

  4. bzoj 1787 Meet 紧急集合

    Meet 紧急集合 这个题是在脖子oj(清北某奆佬给起的名字)八中oj(大视野在线评测)上的. 给出bzoj链接. 这个题还是求最近公共祖先的问题. 而该题不同于别的题,它是需要求三个点的最近公共祖先 ...

  5. Java并发编程:用AQS写一把可重入锁

    Java并发编程:自己动手写一把可重入锁详述了如何用synchronized同步的方式来实现一把可重入锁,今天我们来效仿ReentrantLock类用AQS来改写一下这把锁.要想使用AQS为我们服务, ...

  6. UVA11090 Going in Cycle!! 【SPFA】

    题意:求一个无向图的边权平均值最小的环 思路:假设环中Σwi/t<ans 那变形一下就是Σwi<ans*t → Σ(wi-ans)< 0 这样就可以二分答案做了 #include & ...

  7. hdu 4474

    //因为n是小于等于10000可以利用这点进行搜索对n取余则余数为零时就为所找的.因为他的余数肯定小于10000所以不会无休止下去 #include<stdio.h> #include&l ...

  8. iOS tableview上textView在编辑状态时,tableview自动上移的功能

    在viewcognroller中,添加tableview时, tableview中cell上的textField如果吊起键盘时,tableview时可以自动上移,但是如果是textView吊起键盘,t ...

  9. POJ 3461 字符串出现次数 && HDU1711 字符串第一次出现的位置 模板题

      Oulipo Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 48387   Accepted: 19261 Descri ...

  10. Spring实战Day2

    创建对象之后如何体现对象之间的依赖? Spring容器负责创建Bean和依赖注入,那么Spring是怎么将Bean装配在一起的呢? Spring提供了三种方式装配机制 1.隐式的bean发现机制和自动 ...