说说设计模式~适配器模式(Adapter)
之前和大家一起谈了工厂模式和单例模式,今天来看一下另一种非常常用的模式,它就是适配器模式,第一次看到这个模式是通过“张逸”老师的“设计之道”这篇文章,在这里表adapter讲的很透彻,今天把张老师的文章拿过来,分享给大家!
何时能用到它?
对于一个软件生产商A来说,在过去的20年里,它们主要生产收音机,包括最早的老式半导体和现代的数字收音机,总之,是收音机。但不知道从什么时候开始,MP4媒体播放器出现了,这使得A生产商不得不去招新人,去生产适合大家的mp4播放器,这东西很好,能听音乐,看电影,比20年前的收音机好多了!
正在A生产商洋洋得意时,突然有个客户投诉他们,说你们的东西为何没有收音机的功能,我想叫广播!这下可让A生产商发愁了,它马上找到了公司的技术总监,CTO是个很厉害的岗位,它们无所不能,只要你有需求,我们就可以给你实现!CTO是如何让mp4播放器具体收音机功能的呢?大家继续看
适配器模式的结构图
适配器模式实现说明
媒体播放接口IMedia
视频实现抽象类VideoMedia
音频实现抽象类AudioMedia
mp4播放器实现类:mp4Media和mp3Media,可能还有FlvMedia等
收音机接口IRadio
收音机抽象类Radio
收音机FM调频实现类FmRadio
收音机FM调频与媒体播放器的适配器FmAdapter
适配器模式的C#实现
#region adapter[播放器适配器] #region 媒体播放器 interface IMedia { void Play(); void Stop(); void Next(); void Prev(); void Pause(); void OpenFile(); void CloseFile(); } abstract class AudioMedia : IMedia { public virtual void Play() { throw new NotImplementedException(); } public void Stop() { throw new NotImplementedException(); } public void Next() { throw new NotImplementedException(); } public void Prev() { throw new NotImplementedException(); } public void Pause() { throw new NotImplementedException(); } public void OpenFile() { throw new NotImplementedException(); } public void CloseFile() { throw new NotImplementedException(); } } abstract class VideoMedia : IMedia { public virtual void Play() { throw new NotImplementedException(); } public void Stop() { throw new NotImplementedException(); } public void Next() { throw new NotImplementedException(); } public void Prev() { throw new NotImplementedException(); } public void Pause() { throw new NotImplementedException(); } public void OpenFile() { throw new NotImplementedException(); } public void CloseFile() { throw new NotImplementedException(); } } class Mp3Media : AudioMedia { public override void Play() { base.Play(); Console.WriteLine("播放mp3"); } } class Mp4Media : VideoMedia { public override void Play() { base.Play(); Console.WriteLine("播放mp4"); } } #endregion #region 收音机 interface IRadio { void Receive(); void Stop(); void TurnOn(); void TurnOff(); void Change(bool direction); } abstract class Radio : IRadio { public virtual void Receive() { throw new NotImplementedException(); } public void Stop() { throw new NotImplementedException(); } public void TurnOn() { throw new NotImplementedException(); } public void TurnOff() { throw new NotImplementedException(); } public virtual void Change(bool direction) { throw new NotImplementedException(); } } class FmRadio : Radio { public override void Receive() { base.Receive(); Console.WriteLine("接口FM频段"); } public override void Change(bool direction) { base.Change(direction); Console.WriteLine("改变FM频段"); } } #endregion #region 收音机到媒体播放器的适配器 class FMAdapter : Radio, IMedia { //! 适配器通过Radio去实现了IMedia接口 public void Play() { base.TurnOn(); base.Receive(); } public void Stop() { base.TurnOff(); } public void Next() { base.Change(true); } public void Prev() { base.Change(false); } public void Pause() { throw new NotImplementedException(); } public void OpenFile() { throw new NotImplementedException(); } public void CloseFile() { throw new NotImplementedException(); } } #endregion #endregion
这样我们就实现了Radio与Media两大对象的联系,而这种联系是在不破坏对象本身的基础上实现的,这种实现的过程就是适配器模式实现的过程!
感谢GOF,感谢张逸老师!