Adapter模式进行代码重构
Adapter(适配器)模式主要是将一个类的某个接口转换成一个兼容的接口。
下面是实现一个商品检索的示例
【Bad Code】
public class Product
{
}
public class ProductRepository
{
public IList<Product> GetAllProductsIn(int categoryId)
{
IList<Product> products = new List<Product>();
//从数据库中读取Product数据
return products;
}
}
public class ProductService
{
private ProductRepository _productRepository;
public ProductService()
{
_productRepository = new ProductRepository();
}
public IList<Product> GetAllProductsIn(int categoryId)
{
IList<Product> products;
string storegeKey = string.Format("products_in_category_id_{0}", categoryId);
products = (List<Product>)HttpContext.Current.Cache.Get(storegeKey);
if (products == null)
{
products = _productRepository.GetAllProductsIn(categoryId);
//将商品列表保存到缓存中
HttpContext.Current.Cache.Insert(storegeKey, products);
}
return products;
}
}
这段代码中的主要问题:
- ProductService类强依赖ProductRepository类。
- 强依赖于HttpContext缓存。
【Code Refactoring】
public class Product
{
}
public class ProductRepository : IProductRepository
{
public IList<Product> GetAllProductsIn(int categoryId)
{
IList<Product> products = new List<Product>();
//从数据库中读取Product数据
return products;
}
}
public class ProductService
{
//private ProductRepository _productRepository;
//依赖抽象,而不是依赖具体
private IProductRepository _productRepository;
private ICacheStorage _cacheStorage;
//通过构造函数注入,由客户端代码去实现IProductRepository、ICacheStorage接口
public ProductService(IProductRepository productRepository, ICacheStorage cacheStorage)
{
_productRepository = productRepository;
_cacheStorage = cacheStorage;
}
public IList<Product> GetAllProductsIn(int categoryId)
{
IList<Product> products;
string storegeKey = string.Format("products_in_category_id_{0}", categoryId);
// products = (List<Product>)HttpContext.Current.Cache.Get(storegeKey);
//不再依赖HttpContext缓存
products = _cacheStorage.Retrieve<List<Product>>(storegeKey);
if (products == null)
{
products = _productRepository.GetAllProductsIn(categoryId);
//将商品列表保存到缓存中
//HttpContext.Current.Cache.Insert(storegeKey, products);
_cacheStorage.Store(storegeKey, products);
}
return products;
}
}
public interface IProductRepository
{
IList<Product> GetAllProductsIn(int categoryId);
}
public interface ICacheStorage
{
void Remove(string key);
void Store(string key, object data);
//检索
T Retrieve<T>(string key);
}
/// <summary>
/// HttpContext缓存实现
/// </summary>
public class HttpContextCacheAdapter : ICacheStorage
{
public void Remove(string key)
{
HttpContext.Current.Cache.Remove(key);
}
public T Retrieve<T>(string key)
{
T itemStored = (T)HttpContext.Current.Cache.Get(key);
if (itemStored == null)
itemStored = default(T);
return itemStored;
}
public void Store(string key, object data)
{
HttpContext.Current.Cache.Insert(key, data);
}
}
Adapter模式的目的就是提供一个兼容的接口,比如上面的缓存机制改为Memcached,只需要增加一个MemcachedCacheAdapter的实现,而不用去该ProductService类,也就是达到了对类扩展开放,对修改封闭的原则。
ASP.NET设计模式:https://book.douban.com/subject/6958404/
Adapter模式进行代码重构的更多相关文章
- 代码重构:用工厂+策略模式优化冗余的if else代码块
最近在工作中优化了一段冗余的if else代码块,感觉对设计模式的理解和运用很有帮助,所以分享出来.鉴于原代码会涉及到公司的隐私,因此就不贴出来了.下面以更加通俗易懂的案例来解析. 假如写一个针对员工 ...
- 代码重构:用工厂+策略模式优化过多的if else代码块
最近在工作中优化了一段冗余的if else代码块,感觉对设计模式的理解和运用很有帮助,所以分享出来.鉴于原代码会涉及到公司的隐私,因此就不贴出来了.下面以更加通俗易懂的案例来解析. 假如写一个针对员工 ...
- 设计模式C++描述----06.适配器(Adapter)模式
一. 定义 适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. Adapter 模式的两种类别:类模式和对象模式. 二. 举例说明 实际中 ...
- Android Studio在代码重构中的妙用
代码重构几乎是每个程序员在软件开发中必须要不断去做的事情,以此来不断提高代码的质量.Android Stido(以下简称AS)以其强大的功能,成为当下Android开发工程师最受欢迎的开发工具,也是A ...
- .NET应用架构设计—表模块模式与事务脚本模式的代码编写
阅读目录: 1.背景介绍 2.简单介绍表模块模式.事务脚本模式 3.正确的编写表模块模式.事务脚本模式的代码 4.总结 1.背景介绍 要想正确的设计系统架构就必须能正确的搞懂每个架构模式的用意,而不是 ...
- 代码重构 & 常用设计模式
代码重构 重构目的 相同的代码最好只出现一次 主次方法 主方法 只包含实现完整逻辑的子方法 思维清楚,便于阅读 次方法 实现具体逻辑功能 测试通过后,后续几乎不用维护 重构的步骤 1 新建一个方法 ...
- Abstract Server模式,Adapter模式和Bridge模式
简易的台灯 Abstract Server模式 谁拥有接口. 接口属于它的客户,而不是它的派生类. 接口和客户之间的逻辑关系,强于接口和其派生类的逻辑关系. 逻辑关系和实体关系的强度是不一致的.在实体 ...
- 设计模式--适配器(Adapter)模式
今天学习另一个设计模式,适配器(Adapter)模式,这是一个共同方向,但有特殊要求,就应用到此设计模式.写到这里,想起很久以前,有写过一篇<ASP.NET的适配器设计模式(Adapter)&g ...
- Adapter模式
Adapter模式主要用于将一个类的接口转换为另外一个接口,通常情况下再不改变原有体系的条件下应对新的需求变化,通过引入新的适配器类来完成对既存体系的扩展和改造.实现方式主要包括: 1.类的Adapt ...
随机推荐
- 基于三层交换机和基于路由子接口的vlan间路由
1:通过三层交换机实现vlan间的通信:为三层交换机创建vlan,设置交换机的两个SVI,并配置IP地址. (在二层交换机上只能配置一个SVI端口,用来实现交换机交换机远程管理,在三层交换机上可以配置 ...
- 如何用Ettercap实现“中间人攻击”(附下载链接)
什么是“中间人攻击”? 中间人攻击(Man-in-the-Middle Attack,简称“MiTM攻击”)是一种“间接”的入侵攻击,这种攻击模式是通过各种技术手段将受入侵者控制的一台计算机虚拟放置在 ...
- 深入Java集合学习系列:Hashtable的实现原理
第1部分 Hashtable介绍 和HashMap一样,Hashtable也是一个散列表,它存储的内容是键值对(key-value)映射.Hashtable继承于Dictionary,实现了Map.C ...
- winform无边框窗口拖动
无边框的窗口想拖动,只需要在置顶的容器上添加对应的mousedown 和 mousemove 事件就可以实现了.代码如下: //拖动窗口 private Point mPoint = new Poin ...
- css控制table的td宽度
今天发现即使设置table的td.th宽度,仍是不管用,是根据table的td的内容来适应宽度,导致其他的th.td丢失. 下图就是浏览器渲染的table,导致缺失"端口"这一列, ...
- numpy之索引和切片
索引和切片 一维数组 一维数组很简单,基本和列表一致. 它们的区别在于数组切片是原始数组视图(这就意味着,如果做任何修改,原始都会跟着更改). 这也意味着,如果不想更改原始数组,我们需要进行显式的复制 ...
- EntityFramework6.X 之LocalDB&ConnectionString
LocalDB 面向开发人员的SQL Server Express的执行模式,它的安装将复制启动SQL Server数据库引擎所需的最少文件集且使用特定连接字符串来启动连接,它是可以创建和打开SQL ...
- 我来说说XML文件中的xmlns、xmlns:xsi和xsi:schemaLocation的具体含义
文章摘自:https://yq.aliyun.com/articles/40353 http://www.cnblogs.com/zhao1949/p/5652167. ...
- kafka 0.10.2 消息生产者(producer)
package cn.xiaojf.kafka.producer; import org.apache.kafka.clients.producer.*; import org.apache.kafk ...
- stm之SPI通信协议
SPI (Serial Peripheral interface),顾名思义就是串行外围设备接口.SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为P ...