ASP.NET设计模式(一)、适配器模式、依赖注入依赖倒置、空对象模式
鸟随凤鸾,人伴贤良,得以共之,我之幸也。说的是鸟随着鸾凤可以飞的更高远,人和比自己境界高的相处,自己也会得到熏染进步。
一、概述
分享出来简单的心得,望探讨
依赖倒置
依赖注入
Adapter模式
Null模式
二、快速示例
从一个简单的示例开始,业务流程Client通过Service查询产品,基础大概框架如下
关键代码:
class ProductService
{ private ProductRepository _productRepository; public ProductService()
{
_productRepository=new ProductRepository();
} public IList<Product> GerAllProductsIn(int category)
{
IList<Product> products;
string storagekey = string.Format("product_category_id_{0}",category);
products =(List<Product>) HttpContext.Current.Cache.Get(storagekey); if (products==null)
{
products=_productRepository.GetAllProductsIn(category);
HttpContext.Current.Cache.Insert(storagekey,products);
}
return products;
}
}
ProductService
ProductService直接依赖于ProductRepostory属于强耦合。如何理解这种强耦合呢?现在假设客户新产品上架,需要将ProductRepository替换为NewProductRepository,那么就势必要修改ProductService以及所有引用类ProductRepository,也就是高层模块依赖于低层模块。
三、重构
1、依赖倒置
那么究竟何为依赖倒置,它又如何解耦呢。
依赖倒置实际就是就是要依赖于抽象,不要依赖于具体。意思就是面对抽象进行,而不是面对实现进行编程,通过抽象解决客户与实现模块间的耦合关系。依赖倒置两大重要的原则:一是高层模块不应依赖于低层模块,都应依赖于抽象,二是具体实现也应依赖于抽象。
来看怎么做,定义IProductRepostory接口,使ProductRepostory依赖于接口 ,对ProductService重构也依赖于接口
class ProductService
{ private IProductRepository _productRepository; public ProductService()
{
_productRepository=new ProductRepository();
} public IList<Product> GerAllProductsIn(int category)
{
IList<Product> products;
string storagekey = string.Format("product_category_id_{0}",category);
products =(List<Product>) HttpContext.Current.Cache.Get(storagekey); if (products==null)
{
products=_productRepository.GetAllProductsIn(category);
HttpContext.Current.Cache.Insert(storagekey,products);
}
return products;
}
}
ProductService
依赖倒置通过面对抽象从数据类型降低了耦合度,依赖倒置使高层模块依赖于抽象,即只关心new出来的是否是IProductRepository接口的对象而不关心new出来是谁。这样现在需要解决的就是具体实现的创建问题。
2、依赖注入
依赖注入从其初衷的角度解释就是:当类A完成某个工作需要创建B类的实例来协助的时候,把创建协助类B的工作提取出来从外部完成。
依赖注入三种形式:构造器,方法,属性。本文用构造器注入的方式介绍依赖注入
ProductService重构:
public class ProductService
{
private IProductRepository _productRepository; public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository; } .................. }
ProductService
测试代码(即外部):
namespace Patterns.QuickDemp.Tests
{
[TestFixture]
public class ProductServiceTests
{
[Test]
public void Test_Client()
{
//外部创建对象,任何继承抽象的对象皆可注入
AnyProductRepository anyproductrepository = new AnyProductRepository();
//注入
ProductService productService = new ProductService(anyproductrepository);
...........
.......... } }
}
Tests
可以大胆的作如下设想:客户,商家,第三方支付的关系拿来类比,客户直接与商家交易是一种模式。现在依赖反转,银行卡,支付宝,现金券等支付方式全部继承某个接口,支付动作抽象出来,客户选择支付方式然后外部注入,第三方根据注入指定方式完成支付动作。
3、Adapter模式
adapter模式意图描述:将一个类的接口转换成客户希望的接口
问题描述:用户自定义接口ICacheStorage.面向抽象过程中要让HttpContext成为一个实现用户自定义接口的实现。HttpContext是非用户编写的类,所以用到适配器模式
public interface ICacheStorage
{
void Remove(string key);
void Store(string key, object data);
T Retrieve<T>(string storageKey);
}
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<T>(string key)
{
T itemStored = (T)HttpContext.Current.Cache.Get(key);
if (itemStored == null)
itemStored = default(T); return itemStored;
}
}
HttpContextCacheAdapter
仍然依赖倒置依赖注入对Service重构如下:
public class ProductService
{
private IProductRepository _productRepository;
private ICacheStorage _cacheStorage; public ProductService(IProductRepository productRepository, ICacheStorage cacheStorage)
{
_productRepository = productRepository;
_cacheStorage = cacheStorage;
} public IList<Product> GetAllProductsIn(int categoryId)
{
IList<Product> products;
string storageKey = string.Format("products_in_category_id_{0}", categoryId); products = _cacheStorage.Retrieve<List<Product>>(storageKey); if (products == null)
{
products = _productRepository.GetAllProductsIn(categoryId);
_cacheStorage.Store(storageKey, products);
} return products;
}
}
ProductService
4、Null Object 模式
空对象模式:在一些特殊的情况下用户不希望连带的执行某个动作,也不希望传递null在框架里做判断,就用到空对象模式。这个很容易理解,只是让附带动作变为do nothing
public class NullObjectCachingAdapter : ICacheStorage
{
public void Remove(string key)
{
// Do nothing
} public void Store(string key, object data)
{
// Do nothing
} public T Retrieve<T>(string storageKey)
{
return default(T);
}
}
NullObjectCachingAdapter
四、小结
通过依赖注入和依赖倒置,把创建什么样对象的工作交给客户端(Client),降低Service、Repository、Cache之间的耦合度。假如有新的产品,只有实现了IRepositiry接口,在客户端创建对象,注入给service的构造函数就可以了。
ASP.NET设计模式(一)、适配器模式、依赖注入依赖倒置、空对象模式的更多相关文章
- Spring.NET依赖注入框架学习-- 泛型对象的创建和使用
Spring.NET依赖注入框架学习-- 泛型对象的创建和使用 泛型对象的创建方法和普通对象是一样的. 通过构造器创建泛型对象 下面是一个泛型类的代码: namespace GenericsPlay ...
- Java进阶篇设计模式之十三 ---- 观察者模式和空对象模式
前言 在上一篇中我们学习了行为型模式的备忘录模式(Memento Pattern)和状态模式(Memento Pattern).本篇则来学习下行为型模式的最后两个模式,观察者模式(Observer P ...
- Java设计模式之十三 ---- 观察者模式和空对象模式
前言 在上一篇中我们学习了行为型模式的备忘录模式(Memento Pattern)和状态模式(Memento Pattern).本篇则来学习下行为型模式的最后两个模式,观察者模式(Observer P ...
- 设计模式:空对象模式(Null Object Pattern)
设计模式:空对象模式(Null Object Pattern) 背景 群里聊到<ASP.NET设计模式>,这本书里有一个“Null Object Pattern”,大家就闲聊了一下这个模式 ...
- C# 设计模式之空对象模式
最近看了不少的书籍和视频等相关资料,决定自己边学习边写一下个人对设计模式的理解,如果有不对的请大家多多指正. 今天先说说我个人觉得最简单的设计模式 -- [空对象模式] 空对象模式可以减少客户端对对象 ...
- 被遗忘的设计模式——空对象模式(Null Object Pattern)
GoF(四人帮)那本<设计模式 可复用面向对象软件的基础>可谓是设计模式方面的经典之作,其中介绍的23种设计模式, 也可谓是经典中的经典.但是,设计模式的种类绝不仅仅是这23种,除此之外还 ...
- GoLang设计模式12 - 空对象模式
空对象设计模式是一种行为型设计模式,主要用于应对空对象的检查.使用这种设计模式可以避免对空对象进行检查.也就是说,在这种模式下,使用空对象不会造成异常. 空对象模式的组件包括: Entity:接口,定 ...
- ASP.NET Core依赖注入——依赖注入最佳实践
在这篇文章中,我们将深入研究.NET Core和ASP.NET Core MVC中的依赖注入,将介绍几乎所有可能的选项,依赖注入是ASP.Net Core的核心,我将分享在ASP.Net Core应用 ...
- Spring IOC - 控制反转(依赖注入) - 入门案例 - 获取对象的方式 - 别名标签
1. IOC - 控制反转(依赖注入) 所谓的IOC称之为控制反转,简单来说就是将对象的创建的权利及对象的生命周期的管理过程交 由Spring框架来处理,从此在开发过程中不再需要关注对象的创建和生命周 ...
随机推荐
- UVa1424–Salesmen(DP)
题目大意 给定一个包含n(n<=100)个点的无向连通图和一个长度为L的序列A(L<=200),你的任务是修改尽量少的数,使得序列中的任意两个相邻的数或者相同,或者对应图中两个相邻结点 题 ...
- POJ1873 - Balance(01背包)
题目大意 现有一个天平,它有C个挂钩和G个砝码,问有多少种方法可以使得天平平衡(砝码必须用完) 题解 其实就是让背包容量为0的方法有多少种方法,但是这样的话背包容量会出现负数,所以可以平移一下,背包容 ...
- Kooboo中怎么新增一个关联的Details 动态页面。
Kooboo中怎么新增一个关联的Details 动态页面. 有几个要点: 1. Sub Page的Parent Page 必须是英文书写.如果是中文会出现找不到页面 500错误 2. 要在Page M ...
- FPGA开发板
kingst.cnblogs.com 各种应用需要的接口不同: 做数字信号处理的,需要有AD/DA, 做图像处理,需要有图像接口.如果是通信的,需要有通信的接口,例如PCI/LVDS等.... 然后根 ...
- HTML---Android与js交互实例
Android 中可以通过webview来实现和js的交互,在程序中调用js代码,只需要将webview控件的支持js的属性设置为true Android(Java)与JavaScript(HTML) ...
- WINFORM跟随WPF窗体移动
<Window x:Name="mainWindow1" x:Class="WpfApplication9.MainWindow" xml ...
- http://xss.heimaoseoer.com/TIqiri?1413093855
http://xss.heimaoseoer.com/TIqiri?1413093855 xss教程地址
- 在Java项目中整合Scala
Scala是一个运行在Java JVM上的面向对象的语言.它支持函数编程,在语法上比Java更加灵活,同时通过Akka库,Scala支持强大的基于Actor的多线程编程.具有这些优势,使得我最近很想在 ...
- careercup-排序和查找 11.6
11.6 给定M*N矩阵,每一行.每一列都按升序排序,请编写代码找出某元素. 类似leetcode:Search a 2D Matrix 但是与leetcode中这题不同的是下一行的第一个元素不一定大 ...
- j2ee学习笔记 javascript 学习
JavaScript 组成: ECMAScript + BOM + DOM Window对象是JS中的顶层对象 ECMAScript: 规定了一些语法,变量,for循环等等结构 BOM: Browse ...