首页 > 代码库 > 设计模式-适配器模式(Go语言描写叙述)

设计模式-适配器模式(Go语言描写叙述)

在上一篇博客设计模式-策略模式(Go语言描写叙述)中我们用最简单的代码用go语言描写叙述了设计模式中的策略模式,用最简单的实例来描写叙述相信能够让刚開始学习的人能够非常轻松的掌握各种设计模式。继上篇博客,我们接着用相同简单的代码来了解一下适配器模式。

适配器模式介绍

说起适配器模式,相信非常多做android的同学第一印象就是AdapterView的Adapter,那它是干嘛用的呢?为什么要叫adapter呢?要了解这个问题。我们首先来看看适配器模式的定义:

将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类能够一起工作。——Gang of Four

恩,看起来好像有点迷糊,举个样例吧:

我电脑的电源是三个插头(也就是有地线)的那种,不知道为啥学校的插座都是两个插孔的,哎呀,这可咋办啊!同学建议我们买个转换器,这种转换器有三个插孔,我的电源能够插进去,同一时候它还有两个插头,能够插进学校的插座里,嘿嘿,同学真聪明,这么easy的就攻克了我的问题。

在上面的样例里,那个转换器也能够叫做适配器,我们如今要说的适配器模式灵感就是来自上述所述的实际生活中遇到的问题。那在我们程序设计中会遇到什么样的问题呢? 再来看个样例:

应老师的要求,我们如今须要做一个音乐播放器,如今我算是知道一点面向对象的原则了,所以我首先设计了一个接口。这个接口有一个playMusic的方法,接着我非常轻松的利用这个接口设计出了一个音乐播放器,音乐控制器通过调用playMusic能够完美的播放不论什么音乐。啧啧啧,高兴中…老师对我的音乐播放器也非常惬意。只是他又提出了新的需求,让我的音乐播放器也能够播放游戏的声音。并给了我一个播放游戏声音的类。这个类也非常easy。仅仅有一个playSound方法,尽管非常easy,可是如今我困惑了,由于我设计的音乐控制器仅仅认识playMusic而不认识playSound,难道我要又一次设计我的音乐控制器吗?正当我苦恼的时候,同学出如今了我身后,轻声的告诉我:“适配器模式能够完美的解决你的问题,你仅仅须要写一个Adapter实现你的音乐播放接口,在这个Adapter的playMusic中去调用游戏声音播放器的playSound方法就能够了。

”听了同学的话。我突然恍然大悟。原来这就是适配器模式!

好了。通过上面的三个小段子,相信大家对适配器模式应该了有了大概的认识,以下还是用一张结构图来清晰的描写叙述一下什么是适配器模式吧。

技术分享

通过上面的图我们也能够看出来,适配器要做的事情就是让我们写的野实现适配到系统须要的标准实现上。以下我们迅速进去代码模式,让代码告诉我们适配器模式张啥样!

代码实现

代码实现环节,我们还是用上面那个音乐播放器的样例,首先设计一个音乐播放的接口:

package player

type Player interface {
    PlayMusic()
}

这个接口仅仅有一个方法PlayMusic,系统通过调用PlayMusic这种方法达到播放音乐的目的。

在来看看我们播放音乐的实现。

package player
import "fmt"

type MusicPlayer struct {
    Src string
}

func (p MusicPlayer) PlayMusic() {
    fmt.Println("play music: " + p.Src)
}

MusicPlayer有一个方法是PlayMusic(),所以它实现了Player接口。来让我们的音乐播放器播放器来吧,

package main
import . "./player"

func main() {
    var player Player = MusicPlayer {Src:"music.mp3"}
    play(player)
}

func play(player Player) {
    player.PlayMusic()
}

代码也超级简单,一个play方法去调用了Player的实现的PlayMusic方法。

来看看结果,
技术分享

如今我们的音乐播放器能够播放歌曲了。仅仅须要给出一个歌曲的路径就ok,只是如今我们还须要播放游戏声音。而且给了我们一个这种实现。

package player
import "fmt"

type GameSoundPlayer struct {
    Src string
}

func (p GameSoundPlayer) PlaySound() {
    fmt.Println("play sound: " + p.Src)
}

GameSoundPlayer也是有一个Src属性,也有一个方法,只是这种方法叫PlaySound。并非我们须要的PlayMusic,那可咋办呢?别忘了咱们的play方法
须要的是一个Player的实现,并自己主动调用了PlayMusic方法,以下本节的主角-GameSoundAdapter出场。

package player

type GameSoundAdapter struct {
    SoundPlayer GameSoundPlayer
}

func (p GameSoundAdapter) PlayMusic() {
    p.SoundPlayer.PlaySound()
}

GameSoundAdapter有一个GameSoundPlayer类型的属性。它就是我们上面的那个游戏声音播放器。GameSoundPlayer另一个方法名字叫PlayMusic。所以GameSoundPlayer实现了Player接口,我们能够把它用于player方法中,在PlayMusic中我们是调用的GameSoundPlayerPlaySound来播放声音的。


来看看我们这个适配器适配的咋样,

package main
import . "./player"

func main() {
    gameSound := GameSoundPlayer {Src:"game.mid"}
    gameAdapter := GameSoundAdapter {SoundPlayer:gameSound}
    play(gameAdapter)
}

func play(player Player) {
    player.PlayMusic()
}

看main函数中,首先我们还是有一个GameSoundPlayer类型的变量,然后将它赋值给了GameSoundAdapterSoundPlayer属性。以下调用GameSoundAdapterPlayMusic方法,就能够间接的调用GameSoundPlayerPlaySound方法了,这样我们就轻松的将GameSoundPlayer适配到了Player
来看看结果:
技术分享

总体来看我们的代码还是非常easy,只是简单的代码已经将适配器模式解说的非常清晰了,那最后我们来思考一个问题,适配器模式体现了哪些面向对象的设计原则呢?针对接口编程有木有? 开闭原则有木有?

好了。适配器模式我们就讲到这里,最后是文章的实例代码下载:http://download.csdn.net/detail/qibin0506/9420484

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

设计模式-适配器模式(Go语言描写叙述)