设计模式(三)-结构型模式(1)-适配器模式

news2024/11/23 3:48:25

一、为何需要适配器模式(Adapter)?

在软件设计中,某个模块里有很多公用的功能接口,其中有些公用接口需要用到不同的类当中时,会出现接口不兼容的问题。因为这些不同的类对这个相同任务的接口,都有各自代码逻辑的要求。于是每当客户对这个接口提出新需求,就会再创建一个类,再把所有方法实现一遍,就显得代码很臃肿。为了解决这个问题,只改写需要适配的某个功能,就用到了适配器模式。

比如在文件操作的模块中,都有获取文件属性、读写文件操作等共同的功能接口。在原需求里,已存在保存 txt 文件的功能。当客户有新需求时,需要扩展保存图片文件的功能。这就出现了一个问题:保存 txt 文件和保存图片虽然都是保存操作的任务,但是实现的代码逻辑并不相同。


       //保存txt文件
        public void SaveFile()
        {
            StreamWriter sw = new StreamWriter("test.txt");
            sw.Write("HelloWorld!");
            sw.Dispose();
        }

        //保存图片文件
        public void SaveFile()
        {
            //data 里随便写的数据,不要太认真
            byte[] data = { 11,22,33,44,55};
            MemoryStream ms = new MemoryStream(data);

            Image img = Image.FromStream(ms);
            img.Save("test.jpeg", ImageFormat.Jpeg);
            ms.Dispose();
        }

//保存任务相同:SaveFile。但是实现的代码逻辑不同

特点:
将一个类的接口转换成客户希望的另外一个接口,以解决接口不兼容的问题。(这里的接口不是指 C# 中的 interface,而是一个功能接口)

结构:
目标(Target):定义 Client 需要使用的功能接口。
被适配(Adaptee):定义一些在 Target 已经存在且需要适配的功能接口。
适配器(Adapter):主要负责将 Adaptee 功能接口转换为跟 Target 匹配的功能接口。
客户(Client):使用做了兼容处理的功能接口。

适合应用场景特点:

  • 这个接口具有相同的任务。(比如所有类型的文件共有读写保存的功能接口。)
  • 需要适配相同任务但工作方式不同的接口。(比如不同类型文件保存的方式不同。)

主要两种适配器模式:

  • (1)对象适配器模式
    (处理指定某些功能接口不兼容的问题;Target 派生给 Adapter,Adapter 包装一个需要 Adaptee 的类实例。注重对象组合关系)
  • (2)类适配器模式
    (处理指定某些功能接口不兼容的问题;Target 派生给 Adapter, Adaptee 也派生给 Adapter,特点为多重继承。注重类之间的继承关系)

注:==在工作中推荐使用对象适配器模式。==因为如果使用类适配器,类继承关系就会使得代码结构紧耦合,修改某个基类时就会影响子类。而对象适配不仅满足用户期待的需求,还能降低代码之间的耦合性。

对象适配模式:

请添加图片描述

类适配模式:

请添加图片描述

二、例子

需求:

在迭代版本中,客户希望在保存文本文件功能的基础上,还想要增加对一个图片文件进行保存的功能。并且在将来,可能还会扩展对其他类型文件进行保存的功能。

1、对象适配器模式:


    //目标类:接口、抽象类、具体类都可作为目标
    public class FileOperateTarget
    {
        //保存文本文件
        public virtual void Request()
        {
            Console.WriteLine("Save a string content as the txt,xml,ini...");
        }

        //其他所有要实现的方法
        //(比如获取文件属性的方法,设置默认打开方式的方法等,都是任何类型文件共有的方法)...

        //如果存在代码逻辑不同的方法,则可由适配器模式进行处理。
        //(比如在此例子中,保存文件的方法)
    }

    //被适配类:保存图片文件
    public class ImageFileAdaptee
    {
        public virtual void SpecificRequest()
        {
            Console.WriteLine("Save a Image content as the Img File.");
        }
    }

    //适配器类:主要负责将 Adaptee 类对象进行组合来适配共同方法。
    public class ImageFileAdapter : FileOperateTarget
    {
        //包装一个被适配类的对象(Adaptee 对象)
        private ImageFileAdaptee imageFileAdaptee = new ImageFileAdaptee();
        public override void Request()
        {
            //适配功能的转换工作,把源接口 Request 转换成目标接口 SpecificRequest
            imageFileAdaptee.SpecificRequest();
        }
    }

    //Client
    class Program
    {
        static void Main(string[] args)
        {
            FileOperateTarget target = new ImageFileAdapter();
            target.Request();
            Console.ReadLine();
        }
    }

2、类适配器模式:


    //目标接口:由于在C# 中类只支持单继承,而接口可支持多重继承。所以目标只能是接口 
    public interface IFileOperateTarget
    {
        void Request();
    }

    //被适配类:保存图片文件
    public class ImageFileAdaptee
    {
        public virtual void SpecificRequest()
        {
            Console.WriteLine("Save a Image content as the Img File.");
        }
    }

    //适配器类:主要继承 Adaptee 类 和 Target 类,实现目标接口的转换。
    public class ImageFileAdapter : ImageFileAdaptee, IFileOperateTarget
    {
        public void Request()
        {
            //适配功能的转换工作
            this.SpecificRequest();
        }
    }

    //Client
    class Program
    {
        static void Main(string[] args)
        {
            IFileOperateTarget target = new ImageFileAdapter();
            target.Request();
            Console.ReadLine();
        }
    }

三、缺省适配器模式

  • 特殊的适配器模式,不是主要的模式;一般缺少 Adaptee 结构。
  • 专门处理指定某些功能接口不兼容的问题,而其他所有功能接口都出于未处理状态,即空方法。

请添加图片描述

缺省适配器模式:

    //目标接口
    public interface IFileOperateTarget
    {

        void Request();
        //其他抽象方法...
        void ReadFile();
        void GetFileInfo();
    }
   
    //适配器类:实现接口中抽象方法为空方法
    public class DefaultAdapter : IFileOperateTarget
    {
        public virtual void Request() { }
        public virtual void ReadFile() { }
        public virtual void GetFileInfo() { }
    }

    //Client
    public class ClientImage : DefaultAdapter
    {
        //只使用这个功能
        public override void Request()
        {
            Console.WriteLine("Save a Image content as the Img File.");
        }

        
    }

    //Client:以后有新需求时,可扩展此功能的代码逻辑
    public class ClientWord : DefaultAdapter
    {
        public override void Request()
        {
            Console.WriteLine("Save a Word content as the Word File.");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ClientImage clientImage = new ClientImage();
            clientImage.Request();

            ClientWord clientWord = new ClientWord();
            clientWord.Request();

            Console.ReadLine();
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1306599.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全栈必备——网络编程基础

我们是幸运的,因为我们拥有网络。网络是一个神奇的东西,它改变了你和我的生活方式,改变了整个世界。 然而,网络的无标度和小世界特性使得它又是复杂的,无所不在,无所不能,以致于我们无法区分甚至…

镭速助力集成绘图建模工具加速文件传输速度

在当前信息化社会中,绘图建模工具已经成为许多人不可或缺的伙伴。无论是学习、工作还是生活,这些工具都能够在表达思想、设计方案以及展示成果等方面发挥重要作用。然而,随着绘图建模工具功能的日益强大,用户创作的文件也变得越来…

基于ssm大学生创新创业平台项目管理子系统设计与实现论文

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对大学生创新创业项目信息管理混乱,出错率高,信…

js基础:简介、变量与数据类型、流程循环控制语句、数组及其api

JS基础:简介、变量与数据类型、流程循环控制语句、数组及其api 一、简介 1、js概述 tip:JavaScript是什么? 有什么作用? JavaScript(简称JS)是一种轻量级的、解释性的编程语言,主要用于在网页…

java系列-LinkedHashMap怎么实现LRU

1.定义变量accessOrder public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {final boolean accessOrder;public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {super(initialCapacity, loadFactor…

小间距LED显示屏的芯片扮演的关键角色

LED屏幕由数万颗灯珠封装而成&#xff0c;包含驱动芯片、PCB板、电阻、电容、模组套件和箱体等&#xff0c;形成一块高清LED显示屏。芯片的质量直接影响整个屏幕的品质、稳定性和性能。那么&#xff0c;什么是细间距LED显示屏&#xff1f;小间距LED显示屏芯片具体有何作用呢&am…

设计模式(2)--对象创建(1)--抽象工厂

1. 意图 提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。 2. 四种角色 抽象产品(Product)、具体产品(Concrete Product)、抽象工厂(Abstract Factory)、具体工厂(Concrete Factory)。 3. 优点 3.1 分离了具体的类。Client只需使用抽象工厂类…

易生支付与青岛国资之间的合作即将成为现实。青岛国资决定以曲线入股易生支付。

易生金服的次要股权可能会有新的控制方。 根据西米支付网的消息&#xff0c;经营支付服务的持牌机构“易生支付”的唯一股东“易生金服”的第二大股东凯撒同盛发展股份有限公司的控股权将转让给青岛环海湾文化旅游发展有限公司&#xff0c;同时实际控制权也将交由青岛市市北区国…

java ATM swing窗体转账,取款,存款等

ATM 转账&#xff0c;取款&#xff0c;存款等等 开发环境 开发语言为Java&#xff0c;开发环境Eclipse或者IDEA都可以。 系统框架 利用JDK自带的 框架开发&#xff0c; 纯窗体模式&#xff0c;直接运行Main文件即可以。 涉及主要技术 银行ATM系统 系统用Java语言编写&a…

抖店做起来到底有多难?带你揭露抖音电商的真相!

我是电商珠珠 无论是谁问抖店还能做吗&#xff1f;基本上答案都是肯定的。他们只会说做店很简单&#xff0c;而不会告诉你做电商的压力&#xff0c;以及最真实的投资。 做抖店的风险他们都是一笔带过&#xff0c;好像无论是谁都能做一样。大部分电商公司都会让你做无货源&…

火力发电厂防雷及浪涌防护解决方案

火力发电厂是一种利用燃料燃烧产生的热能驱动汽轮机发电的设施&#xff0c;是目前世界上最常见的发电方式之一。火力发电厂的运行需要大量的电气设备&#xff0c;如辅机马达、通信系统、MIS系统、DCS系统等&#xff0c;这些设备对雷电分敏感&#xff0c;特别是DCS系统&#xff…

如何实现nacos的配置的热更新

我们在使用nacos进行修改配置后&#xff0c;需要微服务无需重启即可让配置生效&#xff0c;也就是使配置进行热更新我们可以采用下面的两种方式进行配置的热更新操作 方式一&#xff1a;在Value所注入的变量的类上添加注解RefreshScope RestController RequestMapping("/o…

Kubernetes(k8s)集群部署----->超详细

Kubernetes&#xff08;k8s&#xff09;集群部署-----&#xff1e;超详细 一、资源准备二、安装准备2.1 主机环境设置2.1.1 关闭操作系统防火墙、selinux2.1.2 关闭swap交换分区2.1.3 允许iptables检测桥接流量&#xff08;可选&#xff09; 2.2 安装Docker环境2.3 安装Kubeadm…

34、卷积实战 - 手写一个基础卷积算法

前面基本上把卷积这一算法的原理和公式介绍完了,如果还有不懂的,可以多翻几遍前面的章节内容,深入理解一下。 本节加一个实战,大家可以手动来实现一个卷积算法,本文中以 python 代码为例,C++ 的代码可以查看本节后面的链接。 说到卷积实现,其实就是自己手写一个卷积算…

pycharm中py文件设置参数

在py文件中右键 直接对应复制进去即可

python matplotlib set_aspect

说明: # 设置轴比例相等&#xff0c;以获得圆柱体视角 ax.set_aspect(equal) 代码案例: import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import numpy as np# 创建数据 theta np.linspace(0, 2*np.pi, 100) z np.linspace(0, 1, 100) r z**2 …

Llama2-Chinese-7b-Chat安装部署

文章目录 前言一、文件介绍 &#x1f4c1;二、环境配置 ♟三、Llama2-Chinese-7b-Chat下载 ⏬总结 前言 本文主要介绍如何使用Llama2-Chinese-7b-Chat&#xff0c;最后的效果如图所示&#xff1a; 一、文件介绍 &#x1f4c1; ⬇️ 下载地址&#xff1a;https://pan.baidu.…

Facebook运营技巧详解,Facebook多店铺如何运营?

在前不久的文章中就讲过Facebook养号和广告的投放技巧&#xff0c;今天东哥就趁热打铁来接着讲讲Facebook的运营技巧&#xff0c;现在做外贸和跨境电商的人基本上都用过Facebook&#xff0c;像在流量这么庞大的平台上想要抓住更多机遇&#xff0c;懂得一些运营技巧是必不可少的…

室内空气污染愈演愈烈,新风系统如何实现呼吸自由

室内空气污染到底有多可怕&#xff1f;有研究发现&#xff0c;室内空气污染比室外空气污染严重2~3倍&#xff0c;甚至几十倍&#xff0c;我国每年有11.1万人因室内空气污染死亡&#xff0c;全球更是高达430万人&#xff0c;68%的人体疾病与室内污染有关&#xff0c;90%的白血病…

c++线程同步之条件变量

c线程同步之条件变量 ​ 条件变量是C11提供的另外一种用于等待的同步机制&#xff0c;它能阻塞一个或多个线程&#xff0c;直到收到另外一个线程发出的通知或者超时时&#xff0c;才会唤醒当前阻塞的线程。条件变量需要和互斥量配合起来使用&#xff0c;C11提供了两种条件变量…