23种设计模式之适配器模式(Adapter Pattern)
适配
即在不改变原有实现的基础上,将原先不兼容的接口转换为兼容的接口。
例如:二转换为三箱插头,将高电压转换为低电压等。
动机(Motivate):
在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。
那么如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?这就是本文要说的Adapter 模式。
意图(Intent):
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
-------《设计模式》GOF
抽象的 UML 类图
4 种角色:Adaptee(被适配),Adapter(适配者),Client(使用场景),Target(目标对象)。
Adaptee(被适配):不是 -er 结尾的哦,之前的 Portal(入口)类作为被适配者。
Adapter(适配者):作为 Adaptee 和 Target 的媒介,进行调节。
Client(使用场景):一个调用的入口,以 Main() 作为入口函数。
Target(目标对象):调节(适配)后的输出,之前的 IOutput 接口和 Export 类都是作为 Target 对象。

图:类适配器(使用继承)

图:对象适配器(使用委托)
/// <summary>
/// 数据访问接口
/// </summary>
public interface IHelper
{
void Add<T>();
void Delete<T>();
void Update<T>();
void Query<T>();
}
public class MysqlHelper : IHelper
{
public void Add<T>()
{
Console.WriteLine("This is {0} Add", this.GetType().Name);
}
public void Delete<T>()
{
Console.WriteLine("This is {0} Delete", this.GetType().Name);
}
public void Update<T>()
{
Console.WriteLine("This is {0} Update", this.GetType().Name);
}
public void Query<T>()
{
Console.WriteLine("This is {0} Query", this.GetType().Name);
}
}
public class OracleHelper : IHelper
{
public void Add<T>()
{
Console.WriteLine("This is {0} Add", this.GetType().Name);
}
public void Delete<T>()
{
Console.WriteLine("This is {0} Delete", this.GetType().Name);
}
public void Update<T>()
{
Console.WriteLine("This is {0} Update", this.GetType().Name);
}
public void Query<T>()
{
Console.WriteLine("This is {0} Query", this.GetType().Name);
}
}
public class SqlserverHelper : IHelper
{
public void Add<T>()
{
Console.WriteLine("This is {0} Add", this.GetType().Name);
}
public void Delete<T>()
{
Console.WriteLine("This is {0} Delete", this.GetType().Name);
}
public void Update<T>()
{
Console.WriteLine("This is {0} Update", this.GetType().Name);
}
public void Query<T>()
{
Console.WriteLine("This is {0} Query", this.GetType().Name);
}
}
上面的代码mysql Oracle SQLserver都实现了IHelper接口这里如果想要对接Redis就需要使用适配器
/// <summary>
/// 第三方提供的 openstack servicestack
/// 不能修改
/// </summary>
public class RedisHelper
{
public void AddRedis<T>()
{
Console.WriteLine("This is {0} Add", this.GetType().Name);
}
public void DeleteRedis<T>()
{
Console.WriteLine("This is {0} Delete", this.GetType().Name);
}
public void UpdateRedis<T>()
{
Console.WriteLine("This is {0} Update", this.GetType().Name);
}
public void QueryRedis<T>()
{
Console.WriteLine("This is {0} Query", this.GetType().Name);
}
}
/// <summary>
/// 通过继承 类适配器模式
/// </summary>
public class RedisHelperClass : RedisHelper, IHelper
{
public void Add<T>()
{
base.AddRedis<T>();
} public void Delete<T>()
{
base.DeleteRedis<T>();
} public void Update<T>()
{
base.UpdateRedis<T>();
} public void Query<T>()
{
base.QueryRedis<T>();
}
}
另外还可以使用适配器执行方法前后做一些拓展
public class CacheHelper
{
public void AddCache<T>()
{
Console.WriteLine("This is {0} Add", this.GetType().Name);
}
public void DeleteCache<T>()
{
Console.WriteLine("This is {0} Delete", this.GetType().Name);
}
public void UpdateCache<T>()
{
Console.WriteLine("This is {0} Update", this.GetType().Name);
}
public void QueryCache<T>()
{
Console.WriteLine("This is {0} Query", this.GetType().Name);
}
}
/// <summary>
/// 通过组合 对象适配器模式
///
/// 组合优于继承
/// </summary>
public class RedisHelperObject : IHelper
{
//private RedisHelper _RedisHelper = new RedisHelper();
private RedisHelper _RedisHelper = null; private CacheHelper _CacheHelper = new CacheHelper();
public RedisHelperObject(RedisHelper redisHelper)//可能是一个抽象接口,注入进来
{
this._RedisHelper = redisHelper;
} public RedisHelperObject()
{
this._RedisHelper = new RedisHelper();
} public void Add<T>()
{
this._CacheHelper.AddCache<T>();
this._RedisHelper.AddRedis<T>();
} public void Delete<T>()
{
this._RedisHelper.DeleteRedis<T>();
} public void Update<T>()
{
this._RedisHelper.UpdateRedis<T>();
} public void Query<T>()
{
this._RedisHelper.QueryRedis<T>();
}
}
前端调用
Console.WriteLine("*****************************");
{
IHelper helper = new SqlserverHelper();
helper.Add<Program>();
helper.Delete<Program>();
helper.Update<Program>();
helper.Query<Program>();
}
Console.WriteLine("*****************************");
{
IHelper helper = new MysqlHelper();
helper.Add<Program>();
helper.Delete<Program>();
helper.Update<Program>();
helper.Query<Program>();
}
Console.WriteLine("*****************************");
{
IHelper helper = new OracleHelper();
helper.Add<Program>();
helper.Delete<Program>();
helper.Update<Program>();
helper.Query<Program>();
}
Console.WriteLine("*****************************");
{
IHelper helper = new RedisHelperClass(); //new RedisHelper();
helper.Add<Program>();
helper.Delete<Program>();
helper.Update<Program>();
helper.Query<Program>();
}
{
//侵入性特别强
RedisHelperClass helper = new RedisHelperClass();
helper.Add<Program>();
//helper
}
Console.WriteLine("*****************************");
{
IHelper helper = new RedisHelperObject(); //new RedisHelper();
helper.Add<Program>();
helper.Delete<Program>();
helper.Update<Program>();
helper.Query<Program>();
}
Adapter模式的几个要点:
Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用。
GOF23定义了两种Adapter模式的实现结构:对象适配器和类适配器。但类适配器采用“多继承”的实现方式,带来不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。
Adapter模式可以实现的非常灵活,不必拘泥于GOF23中定义的两种结构。例如,完全可以将Adapter模式中的“现存对象“作为新的接口方法参数,来达到适配的目的。
Adapter模式本身要求我们尽可能地使用”面向接口的编程"风格,这样才能在后期很方便的适配。
.NET框架中的Adapter应用:
(1)在.Net中复用com对象:
Com 对象不符合.net对象的接口
使用tlbimp.exe来创建一个Runtime Callable Wrapper(RCW)以使其符合.net对象的接口。
(2).NET数据访问类(Adapter变体):
各种数据库并没有提供DataSet接口
使用DBDataAdapter可以将任何各数据库访问/存取适配到一个DataSet对象上。
(3)集合类中对现有对象的排序(Adapter变体);
现有对象未实现IComparable接口
实现一个排序适配器(继承IComparer接口),然后在其Compare方法中对两个对象进行比较。
本文参考文档:https://www.cnblogs.com/abcdwxc/archive/2007/09/04/881674.html
https://www.cnblogs.com/liqingwen/p/6560899.html
23种设计模式之适配器模式(Adapter Pattern)的更多相关文章
- 二十四种设计模式:适配器模式(Adapter Pattern)
适配器模式(Adapter Pattern) 介绍将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.示例有一个Message实体类 ...
- 怎样让孩子爱上设计模式 —— 7.适配器模式(Adapter Pattern)
怎样让孩子爱上设计模式 -- 7.适配器模式(Adapter Pattern) 标签: 设计模式初涉 概念相关 定义: 适配器模式把一个类的接口变换成client所期待的还有一种接口,从而 使原本因接 ...
- 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)
原文:乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) 作者:webabc ...
- 【设计模式】适配器模式 Adapter Pattern
适配器模式在软件开发界使用及其广泛,在工业界,现实中也是屡见不鲜.比如手机充电器,笔记本充电器,广播接收器,电视接收器等等.都是适配器. 适配器主要作用是让本来不兼容的两个事物兼容和谐的一起工作.比如 ...
- Java设计模式之适配器模式(Adapter Pattern)
Adapter Pattern的作用是在不改变功能的前提下转换接口.Adapter分为两类,一类是Object Adapter, 还有一类是Class Adapter.因为Class Adapter的 ...
- 【Unity与23种设计模式】适配器模式(Adapter)
GoF中定义: "将一个类的接口转换成为客户端期待的类接口.适配器模式让原本接口不兼容的类能一起合作." 适配器模式与装饰模式有一定的相似之处 两者都是在着手解决C#不能多继承的问 ...
- 23种设计模式之适配器模式(Adapter)
适配器模式将一个接口转换成客户希望的另一个接口,从而使接口不兼容的那些类可以一起工作.适配器模式既可以作为类结构型模式,也可以作为对象结构型模式.在类适配器模式中,通过使用一个具体类将适配者适配到目标 ...
- 夜话JAVA设计模式之适配器模式(adapter pattern)
适配器模式:将一个类的接口,转换成客户期望的另一个接口,让不兼容的接口变成兼容. 1.类适配器模式:通过多重继承来实现适配器功能.多重继承就是先继承要转换的实现类,再实现被转换的接口. 2.对象适配器 ...
- 【UE4 设计模式】适配器模式 Adapter Pattern
概述 描述 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper). 套路 Target(目标抽象类) 目标抽象类定义了客户所需要的接口,可 ...
随机推荐
- unity编辑器扩展_03(在组件中右击创建一个选项,并通过该选项修改该组件下面的字段的值)
在组件中右击创建一个选项代码: [MenuItem("CONTEXT/PlayerHealth/InitHealth")] static void Test5() { ...
- Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value)
Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value) 深度优先搜索的解题详细介绍,点击 给定一个二叉树,在树的最后一行找到最 ...
- 谈谈我对SOFA模块化的理解
今天我们谈谈SOFA模块化,首先看一段SOFA的介绍: SOFABoot是蚂蚁金服开源的基于Spring Boot的研发框架,它在Spring Boot的基础上,提供了诸如 Readiness Che ...
- Windows GIT SSH 免密教程
Windows GIT SSH 免密教程 安装git客户端,最新下载地址如下 https://github.com/git-for-windows/git/releases/download/v2.2 ...
- 从SpringBoot构建十万博文聊聊限流特技
前言 在开发十万博客系统的的过程中,前面主要分享了爬虫.缓存穿透以及文章阅读量计数等等.爬虫的目的就是解决十万+问题:缓存穿透是为了保护后端数据库查询服务:计数服务解决了接近真实阅读数以及数据库服务的 ...
- openSession 与 getCurrentSession的区别
1.openSession 每一次获得的是一个全新的session对象,而getCurrentSession获得的是与当前线程绑定的session对象 package cn.kiwifly.view; ...
- BS/CS 区别
转载自:https://www.cnblogs.com/chenmingjun 一.CS和BS含义: CS即Client/Server(客户机/服务器)结构.C/S结构在技术上很成熟,它的主要特点是交 ...
- 为什么有了Compose和Swarm,还会有Kubernetes的出现?
一.k8s设计思想更先进 k8s的主要设置思想,是从更宏观的角度,以统一的方式来定义任务之间的各种关系 1.k8s的核心功能图 2.k8s的全局架构图 kube-apiserver:API服务 Kub ...
- 2018宁夏邀请赛K题Vertex Covers(高维前缀和 状压 折半
https://vjudge.net/problem/Gym-102222K 题意:给定N点M边的无向图,每个点有点权. 点覆盖表示某个点集S{}覆盖了所有的边,其贡献是S中点权之积. 现在让你求所 ...
- 快速幂 HDU 1061 Rightmost Digit *
Rightmost Digit Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...