设计模式总结-适配器模式

news2024/10/5 17:28:51

适配器模式

    • 模式动机
    • 模式定义
    • 模式结构
    • 适配器模式实例与解析
      • 实例一:仿生机器人
      • 实例二:加密适配器
    • 总结

模式动机

在软件开发中采用类似于电源适配器的设计和编码技巧被称为适配器模式。
通常情况下,客户端可以通过目标类的接口访问它所提供的服务。有时,现有的类可以满足客户类的功能需要,但是它所提供的接口不一定是客户类所期望的,这可能是因为现有类中方法名与目标类中定义的方法名不一致等原因所导致的。
在这种情况下,现有的接口需要转化为客户类期望的接口,这样保证了对现有类的重用。如果不进行这样的转化,客户类就不能利用现有类所提供的功能,适配器模式可以完成这样的转化。
在这里插入图片描述

在适配器模式中可以定义一个包装类,包装不兼容接口的对象,这个包装类指的就是适配器(Adapter),它所包装的对象就是适配者(Adaptee),即被适配的类。
适配器提供客户类需要的接口,适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适配器模式的模式动机。

模式定义

适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。

模式结构

适配器模式包含如下角色:
Target:目标抽象类
Adapter:适配器类
Adaptee:适配者类
Client:客户类

在这里插入图片描述

适配器模式实例与解析

实例一:仿生机器人

现需要设计一个可以模拟各种动物行为的机器人,在机器人中定义了一系列方法,如机器人叫喊方法cry()、机器人移动方法move()等。如果希望在不修改已有代码的基础上使得机器人能够像狗一样叫,像狗一样跑,使用适配器模式进行系统设计。
在这里插入图片描述

<?xml version="1.0"?>
<config>
    <className>BirdAdapter</className>
</config>
public interface Robot
{
	public void cry();
	public void move();
}

public class Dog
{
	public void wang()
	{
		System.out.println("dog汪汪叫");
	}
	
	public void run()
	{
		System.out.println("dog地上跑");
	}
}

public class DogAdapter extends Dog implements Robot
{
	public void cry()
	{
		System.out.print("robot cry like dog 汪汪叫");
		super.wang();
	}
	
	public void move()
	{
		System.out.print("robot move list dog 地上跑");
		super.run();
	}
}

public class Bird
{
	public void tweedle()
	{
		System.out.println("bird 吱吱叫");
	}
	
	public void fly()
	{
		System.out.println("bird 天上飞");
	}
}
public class BirdAdapter extends Bird implements Robot
{
	public void cry()
	{
		System.out.print("Robot cry like bird 吱吱叫");
		super.tweedle();
	}
	
	public void move()
	{
		System.out.print("Robot move list bird 天上飞");
		super.fly();
	}
}


public class Client
{
	public static void main(String args[])
	{
		Robot robot=(Robot)XMLUtil.getBean();
		robot.cry();
		robot.move();
	}
}


import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
public class XMLUtil
{
 
	public static Object getBean()
	{
		try
		{
			//�����ĵ�����
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			Document doc;							
			doc = builder.parse(new File("config.xml")); 
		
			//��ȡ�����������ı��ڵ�
			NodeList nl = doc.getElementsByTagName("className");
            Node classNode=nl.item(0).getFirstChild();
            String cName=classNode.getNodeValue();
            
            //ͨ����������ʵ�����󲢽��䷵��
            Class c=Class.forName(cName);
	  	    Object obj=c.newInstance();
            return obj;
           }   
           	catch(Exception e)
           	{
           		e.printStackTrace();
           		return null;
           	}
		}
}

实例二:加密适配器

某系统需要提供一个加密模块,将用户信息(如密码等机密信息)加密之后再存储在数据库中,系统已经定义好了数据库操作类。为了提高开发效率,现需要重用已有的加密算法,这些算法封装在一些由第三方提供的类中,有些甚至没有源代码。使用适配器模式设计该加密模块,实现在不修改现有类的基础上重用第三方加密方法。
在这里插入图片描述

public abstract class DataOperation
{
	private String password;
	
	public void setPassword(String password)
	{
		this.password=password;
	}
		
	public String getPassword()
	{
		return this.password;
	}
	
	public abstract String doEncrypt(int key,String ps);
}
public class CipherAdapter extends DataOperation
{
	private Caesar cipher;
	
	public CipherAdapter()
	{
		cipher=new Caesar();
	}
	
	public String doEncrypt(int key,String ps)
	{
		return cipher.doEncrypt(key,ps);
	}
}

public final class Caesar 
{
	public String doEncrypt(int key,String ps)
	{   
		String es="";
		for(int i=0;i<ps.length();i++)
		{
			char c=ps.charAt(i);
			if(c>='a'&&c<='z')
			{
				c+=key%26;
			if(c>'z') c-=26;
			if(c<'a') c+=26;
			}
			if(c>='A'&&c<='Z')
			{
				c+=key%26;
			if(c>'Z') c-=26;
			if(c<'A') c+=26;
			}
			es+=c;
		}
		return es;
	}
}

public class NewCipherAdapter extends DataOperation
{
	private NewCipher cipher;
	
	public NewCipherAdapter()
	{
		cipher=new NewCipher();
	}
	
	public String doEncrypt(int key,String ps)
	{
		return cipher.doEncrypt(key,ps);
	}
}

public final class NewCipher
{
	public String doEncrypt(int key,String ps)
	{ 
		String es="";
		for(int i=0;i<ps.length();i++)
		{
			String c=String.valueOf(ps.charAt(i)%key);
			es+=c;
		}
		return es;
	}
}


{
	public static void main(String args[])
	{
		DataOperation dao=(DataOperation)XMLUtil.getBean();
		dao.setPassword("sunnyLiu");
		String ps=dao.getPassword();
		String es=dao.doEncrypt(6,ps);
		System.out.println("������" + ps);
		System.out.println("������" + es);
	}
}

总结

通过多重继承目标接口和被适配者类方式来实现适配(简单记忆其实还可以用依赖+继承实现)

类适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

对象适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。

接口适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。

实现方式两种:
1.多继承方式,即实现 Target接口 继承 Adaptee类; 上面的例子一方式;
2.继承加依赖方式,即实现Target接口 并复合一个 Adaptee;上面的例子二方式

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

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

相关文章

Redis性能瓶颈与安全隐患排查验证纪实

在写《Redis怎样保证数据安全&#xff1f;》这篇文章&#xff0c;我是有对redis设置密码需要哪些步骤&#xff0c;设置密码的性能损耗有验证的。这就涉及到要对redis的配置做修改。 开始时我是打算采用直接使用redis配置文件的方式。所以我从redis官网下载了一个默认的配置文件…

java实现运行脚本文件

在最近的项目中&#xff0c;有一个需求是前端传给我一个脚本文件&#xff0c;然后我需要运行脚本文件后将结果进行返回&#xff0c;那接下来就让我们看看是怎么做的吧&#xff01; public R runScripts(Integer id) {ScriptsInfo scriptsInfo this.baseMapper.selectById(id);…

影响力营销与AI的结合:Kompas.ai在搭桥角色中的独特价值

在数字化营销的新时代&#xff0c;影响力营销已经成为品牌建立信任和提升市场影响力的有效手段。通过与关键意见领袖&#xff08;KOL&#xff09;的合作&#xff0c;品牌能够利用KOL的信誉和影响力来扩大其市场覆盖范围和提升品牌认知度。然而&#xff0c;寻找与品牌价值观相契…

汇编语言:寻址方式在结构化数据访问中的应用——计算人均收入

有一年多没有在CSDN上发博文了。人的工作重心总是有转移的&#xff0c;庆幸一直在做着有意义的事。   今天的内容&#xff0c;是为汇编语言课程更新一个实验项目。      本方案修改自王爽编《汇编语言》第&#xff14;版P172“实验7寻址方式在结构化数据访问中的应用” …

科普|老隋分享的人力资源项目怎么样?可不可以赚钱?

近年来&#xff0c;随着市场竞争的加剧和企业对人才需求的不断提升&#xff0c;人力资源项目逐渐成为了创业者和投资者关注的焦点。老隋作为一位在人力资源领域深耕多年的专业人士&#xff0c;经常分享关于人力资源项目的见解和经验。那么&#xff0c;老隋分享的人力资源项目究…

Android Glide

1.引入glide implementation com.github.bumptech.glide:glide:4.14.2 // Skip this if you dont want to use integration libraries or configure Glide. annotationProcessor com.github.bumptech.glide:compiler:4.14.2 //Glide 注解处理器 2.AndroidManifest.xml 中添加…

截稿倒计时 CCF-B 推荐会议EGSR’24论文摘要4月9日提交

会议之眼 快讯 第35届EGSR 2024 (Eurographics Symposium on Rendering)即欧洲图形学渲染专题讨论会将于 2024 年 7月3日-5日在英国伦敦帝国理工学院举行&#xff01;在EGSR之前&#xff0c;将有一个全新的联合研讨会&#xff0c;即材料外观建模&#xff08;MAM&#xff09;和…

【如何写论文】解决方案——删除脚注里多余的回车换行,标题的段前磅数消失问题、图像显示不完整、被截断、浮动问题

目录 一、脚注里多余的回车换行无法删除问题1.1、问题描述1.2、解决方案 二、标题前的段前磅数消失问题2.1、问题描述2.2、解决方案 三、图像显示不完整、被截断、浮动问题3.1、问题描述3.2、解决方案 一、脚注里多余的回车换行无法删除问题 1.1、问题描述 一般论文要求需要有…

Unity Toggle组件

Toggle Group组件 Allow Switch Off属性值为false时&#xff0c; 1&#xff0c;Toggle初始时默认会有一个被勾选&#xff08;ison为true&#xff09;&#xff0c;可以自己打勾指定 2&#xff0c;不能取消勾选 Allow Switch Off属性值为true时&#xff0c; 1&#xff0c;Toggl…

无监督学习简介

无监督学习简介 一、定义和核心概念 无监督学习的定义 无监督学习是机器学习的一个关键分支&#xff0c;它涉及到从未标注数据中学习和提取信息。不同于其他学习类型&#xff0c;无监督学习的数据集没有提供任何显式的输出标签或结果。因此&#xff0c;这种学习方法的主要任务…

js计算器实现

文章目录 1. 演示效果2. 分析思路3. 代码实现 1. 演示效果 2. 分析思路 给每个按钮添加点击事件&#xff0c;使用eval()进行计算。 3. 代码实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name&q…

数据生成 | Matlab实现基于DE差分进化算法的数据生成

数据生成 | Matlab实现基于DE差分进化算法的数据生成 目录 数据生成 | Matlab实现基于DE差分进化算法的数据生成生成效果基本描述模型描述程序设计参考资料 生成效果 基本描述 1.Matlab实现基于DE差分进化算法的数据生成&#xff0c;运行环境Matlab2021b及以上&#xff1b; 2.计…

HubSpot如何通过自动化和优化客户服务流程,提升客户满意度和忠诚度?

HubSpot通过自动化和优化客户服务流程&#xff0c;可以有效地提升客户满意度和忠诚度。以下是HubSpot实现这一目标的几个关键步骤&#xff1a; 建立清晰的服务流程&#xff1a;首先&#xff0c;HubSpot帮助企业建立清晰、标准化的客户服务流程。这包括明确的服务阶段定义&…

Codigger Desktop:用户体验与获得收益双赢的革新之作(一)

上周&#xff0c;我们介绍了Codigger Desktop凭借其强大的功能、稳定的性能以及人性化的设计&#xff0c;成为了广大开发者的得力助手。Codigger Desktop除了是开发者的利器外&#xff0c;它以其出色的用户体验和创新的收益模式&#xff0c;为用户提供了一个全新的选择。Codigg…

【线段树】1622. 奇妙序列

本文涉及知识点 设计 数学 线段树 本文基础解法 【设计】 【数学】1622 奇妙序列 LeetCode1622. 奇妙序列 请你实现三个 API append&#xff0c;addAll 和 multAll 来实现奇妙序列。 请实现 Fancy 类 &#xff1a; Fancy() 初始化一个空序列对象。 void append(val) 将整数…

【单片机家电产品--晶闸管(可控硅)】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 单片机家电产品–晶闸管 前言 记录学习单片机家电产品内容 已转载记录为主 一、知识点 1 晶体管和晶闸管之间的区别 晶体管和晶闸管之间的区别 2 什么是可控硅&#xf…

WebKit结构揭秘:探秘网页渲染的魔法之源

一、WebKit之心&#xff1a;渲染引擎的魔力 WebKit的渲染引擎是其核心所在&#xff0c;它犹如一位技艺高超的魔法师&#xff0c;将HTML、CSS和JavaScript的魔法咒语转化为绚丽的网页画面。它解析代码&#xff0c;绘制页面&#xff0c;让网页内容跃然屏上&#xff0c;展现出无尽…

宏的使用(C语言详解)

在写一个代码生成可执行文件的过程需要经过编译和链接&#xff0c;编译又要经过三部&#xff1a;预处理&#xff0c;编译&#xff0c;汇编。 #define定义的变量和宏就是在预处理阶段会处理的。 一个简单的宏定义&#xff1a; #include<stdio.h>; #define Max(a,b) a>…

【微服务】SpringCloud之Feign远程调用

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

Mac安装Docker提示Another application changed your Desktop configuration解决方案

1. 问题描述 Mac安装Docker后&#xff0c;提示Another application changed your Desktop configuration&#xff0c;Re-apply configurations无效 2. 解决方案 在终端执行下述命令即可解决&#xff1a; sudo ln -sf /Applications/Docker.app/Contents/Resources/bin/docke…