博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用依赖倒置和依赖注入实现应用程序解耦
阅读量:6148 次
发布时间:2019-06-21

本文共 5793 字,大约阅读时间需要 19 分钟。

首先,我们虚拟一个系统环境(e-Shop),即网上商店的应用程序,其中有一个应用: 获取指定分类下的所有产品信息。我们按照传统的思路来实现。图1展示了系统的设计图。

 新建一个类库工程EShop.Service. 然后添加相应的类到工程中。

原始程序
namespace EShop.Service {
public class Product {
} public class ProductRepository {
public IList
GetProductsByCategory(int categoryId) {
IList
products = new List
(); //进行数据库操作 return products; } } public class ProductService {
private ProductRepository productRepository; public ProductService() {
productRepository = new ProductRepository(); } public IList
GetProductsByCategory(int categoryId) {
IList
products; string storageKey = String.Format("products_in_category_id_{0}", categoryId); products = (List
)HttpContext.Current.Cache.Get(storageKey); if (products == null) { products = productRepository.GetProductsByCategory(categoryId); HttpContext.Current.Cache.Insert(storageKey, products); } return products; } } }

 从以上的程序段是否能发现不合理之处呢?我归纳了一下,大致有以下几点:

1. ProductService依赖于ProductRepository,一旦后者的API发生变化,则前者必然跟着发生变化。

2. 难以测试ProductService的方法,因为ProductRepository并未真正连接到数据库,另外还依赖于HttpContext,两者之间紧耦合。

3. 目前采用HttpContext来进行缓存,如果要更换缓存机制(如:Velocity或Memcached),ProductService将进行更改。

基于以上几点不合理之处,我们将一一进行重构和优化。

针对1:我们采用依赖倒置原则(Dependency Inversion Principle)——依赖于抽象而不是具体实现来解决。我们加入了接口IProductRepository。

增加接口
public interface IProductRepository {
IList
GetProductsByCategory(int categoryId); } public class ProductRepository : IProductRepository {
//... } public class ProductService {
private IProductRepository productRepository; public ProductService() {
productRepository = new ProductRepository(); } //... }

针对2:我们采用依赖注入原则(Dependency Injection Principle)——通过将抽象注入到构造函数、方法或属性来解决。我们修改ProductService构造函数。

注入构造函数

public class ProductService {
private IProductRepository productRepository; public ProductService(IProductRepository productRepository) {
this.productRepository = productRepository; } //... }

针对3:我们采用适配器模式(Adapter Pattern)——转换已有接口与客户期望的目标接口使之兼容来解决。我们添加了接口ICacheStorage和类HttpContextCacheAdapter。

采用适配器
public interface ICacheStorage {
void Remove(string key); void Store(string key, object data); T Retrieve
(string key); } public class HttpContextCacheAdapter : ICacheStorage public class HttpContextCacheAdapter : ICacheStorage {
public void Remove(string key) {
HttpContext.Current.Cache.Remove(key); } public void Store(string key, object data) {
HttpContext.Current.Cache.Insert(key, data); } public T Retrieve
(string key) {
T item = (T)HttpContext.Current.Cache.Get(key); if (item == null) {
item = default(T); } return item; } } public class ProductService {
private IProductRepository productRepository; private ICacheStorage cacheStorage; public ProductService(IProductRepository productRepository, ICacheStorage cacheStorage) {
this.productRepository = productRepository; this.cacheStorage = cacheStorage; } public IList
GetProductsByCategory(int categoryId) {
IList
products; string storageKey = String.Format("products_in_category_id_{0}", categoryId); products = cacheStorage.Retrieve
>(storageKey); if (products == null) { products = productRepository.GetProductsByCategory(categoryId); cacheStorage.Store(storageKey, products); } return products; } }

综合以上的解决方案,这里贴出重构后完整的代码:

重构后的代码
namespace EShop.Service {
public class Product {
} public interface IProductRepository {
IList
GetProductsByCategory(int categoryId); } public class ProductRepository : IProductRepository {
public IList
GetProductsByCategory(int categoryId) {
IList
products = new List
(); //进行数据库操作 return products; } } public interface ICacheStorage {
void Remove(string key); void Store(string key, object data); T Retrieve
(string key); } public class HttpContextCacheAdapter : ICacheStorage {
public void Remove(string key) {
HttpContext.Current.Cache.Remove(key); } public void Store(string key, object data) {
HttpContext.Current.Cache.Insert(key, data); } public T Retrieve
(string key) { T item = (T)HttpContext.Current.Cache.Get(key); if (item == null) { item = default(T); } return item; } } //有时为方便起见,我们定义空对象(空缓存适配器) public class NullCacheAdapter : ICacheStorage { public void Remove(string key) { } public void Store(string key, object data) { } public T Retrieve
(string key) { return default(T); } } public class ProductService { private IProductRepository productRepository; private ICacheStorage cacheStorage; public ProductService(IProductRepository productRepository, ICacheStorage cacheStorage) { this.productRepository = productRepository; this.cacheStorage = cacheStorage; } public IList
GetProductsByCategory(int categoryId) { IList
products; string storageKey = String.Format("products_in_category_id_{0}", categoryId); products = cacheStorage.Retrieve
>(storageKey); if (products == null) { products = productRepository.GetProductsByCategory(categoryId); cacheStorage.Store(storageKey, products); } return products; } } }

附上重构后的设计图:

转载于:https://www.cnblogs.com/hmiinyu/archive/2011/11/14/2249059.html

你可能感兴趣的文章
Data Wrangling文摘:Non-tidy-data
查看>>
while()
查看>>
常用限制input的方法
查看>>
IIS7下使用urlrewriter.dll配置
查看>>
并行程序设计学习心得1——并行计算机存储
查看>>
JAVA入门到精通-第86讲-半双工/全双工
查看>>
bulk
查看>>
js document.activeElement 获得焦点的元素
查看>>
C++ 迭代器运算
查看>>
【支持iOS11】UITableView左滑删除自定义 - 实现多选项并使用自定义图片
查看>>
day6-if,while,for的快速掌握
查看>>
JavaWeb学习笔记(十四)--JSP语法
查看>>
【算法笔记】多线程斐波那契数列
查看>>
java8函数式编程实例
查看>>
jqgrid滚动条宽度/列显示不全问题
查看>>
在mac OS10.10下安装 cocoapods遇到的一些问题
查看>>
angularjs表达式中的HTML内容,如何不转义,直接表现为html元素
查看>>
css技巧
查看>>
Tyvj 1728 普通平衡树
查看>>
[Usaco2015 dec]Max Flow
查看>>