IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 设计模式之适配器模式 -> 正文阅读

[网络协议]设计模式之适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。可以将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。这里的读卡器就相当于一个适配器。

意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

主要解决:主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。

何时使用:?

  • 系统需要使用现有的类,而此类的接口不符合系统的需要。
  • 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
  • 通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)

如何解决:继承或依赖(推荐)。

关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。

优点:?

  • 可以让任何两个没有关联的类一起运行。
  • 提高了类的复用。
  • 增加了类的透明度。
  • 灵活性好。

缺点:?

  • 过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
  • 由于部分高级语言(C#、Java) 至多继承一个类,所以至多只能适配一个适配者类。

使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

注意事项:适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。

实例应用1:

下面的实例来演示适配器模式的使用。其中,音频播放器设备只能播放 mp3 文件,通过使用一个更高级的音频播放器来播放 vlc 和 mp4 文件。

默认情况下,AudioPlayer只能播放mp3文件,VlcPlayer播放vlc文件,Mp4Player播放mp4文件。如下所示:

?现在我们希望AudioPlayer也能播放vlc文件和mp4文件。也就是说希望能有一个实现了IMediaPlayer,针对IAdvancedMediaPlayer做适配的适配器类MediaPlayerAdapterAdvancedMediaPlayer

同时修改IMediaPlayer接口,让它能根据传入的不同音频类型播放不同类型的文件。

IAdvancedMediaPlayer

namespace Adapter
{
    public interface IAdvanceMediaPlayer
    {
        void PlayVlc(string fileName);

        void PlayMp4(string fileName);
    }
}

IMediaPlayer

namespace Adapter
{
    public interface IMediaPlayer
    {
        void Play(EAudioType audioType, string fileName);
    }
}

VlcPlayer、Mp4Player

using UnityEngine;

namespace Adapter
{
    public class VlcPlayer : IAdvanceMediaPlayer
    {
        public void PlayVlc(string fileName)
        {
            Debug.Log($"Playing vlc file. Name {fileName}");
        }

        public void PlayMp4(string fileName)
        {
        }
    }

    public class Mp4Player : IAdvanceMediaPlayer
    {
        public void PlayVlc(string fileName)
        {
            
        }

        public void PlayMp4(string fileName)
        {
            Debug.Log($"Playing mp4 file. Name {fileName}");
        }
    }
}

适配器类MediaPlayerAdapterAdvancedMediaPlayer?

namespace Adapter
{
    public class MediaPlayerAdapterAdvancedMediaPlayer : IMediaPlayer
    {
        private IAdvanceMediaPlayer _advanceMediaPlayer;

        public MediaPlayerAdapterAdvancedMediaPlayer(EAudioType audioType)
        {
            if (audioType == EAudioType.Vlc)
            {
                _advanceMediaPlayer = new VlcPlayer();
            }
            else if (audioType == EAudioType.Mp4)
            {
                _advanceMediaPlayer = new Mp4Player();
            }
        }

        public void Play(EAudioType audioType, string fileName)
        {
            if (audioType == EAudioType.Vlc)
            {
                _advanceMediaPlayer.PlayVlc(fileName);
            }
            else if (audioType == EAudioType.Mp4)
            {
                _advanceMediaPlayer.PlayMp4(fileName);
            }
        }
    }
}

AudioPlayer

using UnityEngine;

namespace Adapter
{
    public class AudioPlayer : IMediaPlayer
    {
        private MediaPlayerAdapterAdvancedMediaPlayer _mediaAdapter; 
        
        public void Play(EAudioType audioType, string fileName)
        {
            if (audioType == EAudioType.Mp3)
            {
                Debug.Log($"Playing map3 file. Name {fileName}");
            }
            else if (audioType == EAudioType.Vlc ||
                     audioType == EAudioType.Mp4)
            {
                _mediaAdapter = new MediaPlayerAdapterAdvancedMediaPlayer(audioType);
                _mediaAdapter.Play(audioType, fileName);
            }
            else
            {
                Debug.LogError($"Invalid Media. {audioType} Format Not Supported.");
            }
        }
    }
}

AudioPlayer现在可以播放不同类型的音频文件了。

AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.Play(EAudioType.Mp3,"mp3");
audioPlayer.Play(EAudioType.Mp4,"mp4");
audioPlayer.Play(EAudioType.Vlc,"vlc");

实例应用2:

模拟计算机读取SD卡:

创建SD卡的接口及实现类:

    public interface ISDCard
    {
        string ReadSD();

        int WriteSD(string msg);
    }
    
    public class SDCard: ISDCard
    {
        public string ReadSD()
        {
            string msg = "sdcard read a msg :hello word SD";
            return msg;  
        }

        public int WriteSD(string msg)
        {
            Debug.Log($"sd card write msg : {msg}");    
            return 1;   
        }
    }

创建计算机接口及实现类提供读取SD卡方法:

    public interface IComputer 
    {    
        string ReadSD(ISDCard sdCard);
    }

    public class ThinkpadComputer : IComputer
    {
        public string ReadSD(ISDCard sdCard)
        {
            if (sdCard == null)
            {
                throw new NullReferenceException("sd card null");
            }

            return sdCard.ReadSD();
        }
    }

现在去使用计算机实例读取一张SD卡:

  IComputer computer = new ThinkpadComputer();
  ISDCard sdCard = new SDCard();
  computer.ReadSD(sdCard);

我们希望在不改变计算机读取SD卡接口的情况下,读取TF卡,已知TF卡接口及实现类如下:

    public interface ITFCard
    {
        string ReadTF();
        int WriteTF(string msg);
    }
    
    public class TFCard : ITFCard
    {
        public string ReadTF()
        {
            string msg ="tf card reade msg : hello word tf card";        
            return msg;    
        }

        public int WriteTF(string msg)
        {
            Debug.Log("tf card write a msg : {msg}");        
            return 1;    
        }
    }

现在我们需要一个适配器,它实现了ISDCard接口,但传入的是ITFCard,即针对ISDCard兼容ITFCard。

    public class SDAdapterTF : ISDCard
    {
        private ITFCard tfCard;

        public SDAdapterTF(ITFCard tfCard)
        {
            this.tfCard = tfCard;
        }
        public String ReadSD()
        {
            Debug.Log("adapter read tf card ");
            return tfCard.ReadTF();
        }
        
        public int WriteSD(String msg)
        {
            Debug.Log("adapter write tf card");
            return tfCard.WriteTF(msg);
        }
    }

那么现在就可以以ISDCard的实例传入,但内部实现的却是ITFCard的实现方法。

  ITFCard tfCard = new TFCard();
  ISDCard sdCardAdapterTf = new SDAdapterTF(tfCard);
  computer.ReadSD(sdCardAdapterTf);

类图设计如下:

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-09-14 13:44:27  更:2021-09-14 13:44:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 11:56:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计