温故而知新:设计模式之适配器模式(Adapter)
时间:2022-04-23
本文章向大家介绍温故而知新:设计模式之适配器模式(Adapter),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
借用terrylee的原话:
Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用。
适配器模式再次体现了“面向接口编程,而非面向实现编程”这一精神。
场景:
有一个基于数据库的系统,里面的数据库操作就拿最常用的查询来说,主要是用SqlHelper类里的QueryData(string sql)这个方法来处理的,后来意外发现该方法实现上性能并不是最好(或者不能满足新的需要),而这时正好有一个第三方的DbHelper程序集,写得很成熟性能也不错,但唯一不足的是里面的查询方法签名是SelectData(string sql),怎么办?所有引用SqlHelper的地方全部修改,重头编译么?No,没人会想这样
先看下原来的代码:
using System;
using System.Data;
namespace Adapter
{
class Program
{
static void Main(string[] args)
{
IDBHelper dbhelper = new SqlHelper();
dbhelper.QueryData("Select * from TableA");
Console.ReadKey();
}
}
public interface IDBHelper
{
DataSet QueryData(string sql);
}
public class SqlHelper : IDBHelper
{
public DataSet QueryData(string sql)
{
Console.WriteLine("QueryData is Called,the sql is :"{0}"",sql);
return new DataSet();//这里演示起见,就直接返回一个DataSet实例完事 :)
}
}
}
如何在尽量不影响原有客户端代码的情况下,用新的DbHelper来取代旧的SqlHelper呢?
假如第三方的DBHelper结构如下:
/// <summary>
/// 第三方的新dbHelper,实际场景中,这个类通常都是封装在程序集中以dll提供,客户端程序无法修改
/// </summary>
public class DbHelper
{
public DataSet SelectData(string sql)
{
Console.WriteLine("SelectData is Called,the sql is :"{0}"", sql);
return new DataSet();//这里演示起见,就直接返回一个DataSet实例完事 :)
}
}
可以新增一个适配器:
/// <summary>
/// 新增的适配器
/// </summary>
public class DBHelperAdapter : IDBHelper
{
private DbHelper _dbHelper;
public DBHelperAdapter(DbHelper dbHelper)
{
this._dbHelper = dbHelper;
}
public DataSet QueryData(string sql)
{
return _dbHelper.SelectData(sql);
}
}
这样原有的客户端程序,只需要把 IDBHelper dbhelper = new SqlHelper();
改成:
IDBHelper dbhelper = new DBHelperAdapter(new DbHelper()); 就万事大吉了,当然你可以用配置文件+反射,完全解耦,此处略过 反思:
本例中之所以能轻易将新的类替换旧的类,主要得益于旧的代码仅依赖于抽象(即接口IDBHelper),而非具体的实现(即类SqlHelper),否则也不可能达到最终效果。
OO原则中的"面对接口编码","依赖倒置"的妙处也就在于此。
最后给出类图:
- 使用Identity Server 4建立Authorization Server (4)
- 使用Identity Server 4建立Authorization Server (3)
- 使用Identity Server 4建立Authorization Server (2)
- 使用Identity Server 4建立Authorization Server (1)
- Java之异常处理
- 挖洞经验 | 看我如何利用SAML漏洞实现Uber内部聊天系统未授权登录
- 使用ichartjs生成图表
- 使用angular4和asp.net core 2 web api做个练习项目(四)
- list.add(),向List集合插入对象报空指针异常
- 使用angular4和asp.net core 2 web api做个练习项目(三)
- 即学即用系列一:纯函数
- Java之StringBuffer,StringBuilder,Math,Date,SimpleDateFormat,UUID,File
- React编程思想
- 前台分页,以及类别选择
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法